HASHTOOL!' @[TOOL128.ASM9p\BUILDTOOL128 FINDER.DATA p!.TOOL128.MACS.S  VHASH.H&7\M16.HASHTOOL $8 \TOOL128.DOCSP2$* xET! | keep tool128 mcopy tool128.macros ;Orca Macros ************************************************************** * * Hash Tool * * * Reference: Apple IIGS Toolbox Reference, Volume 2, Appendix A * **************************************************************** * * September 1999 -- version 1.0 released. * Only md5 available. * * July 2002 -- version 1.0.1 released. * Andrew's md4 routines added. * * June 2004 -- version 1.0.2 release. * >0>t  ~(EE  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'q0*5 TOOL128.DOCS5B TOOL128.ASMD BUILDTOOL1285TOOL128.MACS.SHASH.H M16.HASHTOOL Fixed memory corruption bug in md4 and md5 if * DBR != PBR. * **************************************************************** ; ; md5 code is a port of md5 written by L. Peter Deutsch, ghost@aladdin.com ; ;Comments from Andrew: ; [md4 code] created by Andrew Roughan 30 June 2002 ; Geoff's md5 implementation was based on L. Peter Deutsch's md5.c ; As md4 and md5 are very similar, I set out to find a way to reuse ; what Geoff had done to create an md4 toolset. ; L. Peter Deutsch does not appear to have implemented md4, so ; I went back to RFC1320 and created C source code for md4 in the style ; that L.Peter Deutsch may have done if he had been inclined. ; By comparing my C code for md4 (in Peter's style) with Peter's C code ; for md5 and looking at Geoff's implementation of md5 as a toolset, ; I was able to easily see where Geoff's code could be reused and ; where modifications were necessary to create md4 subroutines. ; ;............................................................... ; ; Written by Geoff Weiss, geoff@apple2.gs ; ; Copyleft 1999 by Geoff Weiss, geoff@apple2.gs ; ; This source code may only be distributed on A2central, hashtool.gwlink.net ; web site, disks provided by Shareware Solutions II and Juiced.GS, and any ; mailing list run by Geoff Weiss. Any other distribution is prohibited ; and so by deemed illegal. If none of these distribution points are ; available, the code may be distributed anywhere. ; ; Binaries may be distributed by the following methods: ; (source must be provided with binaries) ; A2central libraries ; Shareware Solutions II and Juiced.GS disk collections ; mailing lists run by Geoff Weiss ; Any 3rd party software which requires use of this software. ; ; Prosecution of violators will strictly follow all national and local ; laws. ; ; To avoid incompatible versions of the software to be distributed, it ; is recommended to let Geoff Weiss run a CVS repository for development. ; ;............................................................... ; ; GNU GENERAL PUBLIC LICENSE ; TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION ; ; 0. This License applies to any program or other work which contains ;a notice placed by the copyright holder saying it may be distributed ;under the terms of this General Public License. The "Program", below, ;refers to any such program or work, and a "work based on the Program" ;means either the Program or any derivative work under copyright law: ;that is to say, a work containing the Program or a portion of it, ;either verbatim or with modifications and/or translated into another ;language. (Hereinafter, translation is included without limitation in ;the term "modification".) Each licensee is addressed as "you". ; ;Activities other than copying, distribution and modification are not ;covered by this License; they are outside its scope. The act of ;running the Program is not restricted, and the output from the Program ;is covered only if its contents constitute a work based on the ;Program (independent of having been made by running the Program). ;Whether that is true depends on what the Program does. ; ; 1. You may copy and distribute verbatim copies of the Program's ;source code as you receive it, in any medium, provided that you ;conspicuously and appropriately publish on each copy an appropriate ;copyright notice and disclaimer of warranty; keep intact all the ;notices that refer to this License and to the absence of any warranty; ;and give any other recipients of the Program a copy of this License ;along with the Program. ; ;You may charge a fee for the physical act of transferring a copy, and ;you may at your option offer warranty protection in exchange for a fee. ; ; 2. You may modify your copy or copies of the Program or any portion ;of it, thus forming a work based on the Program, and copy and ;distribute such modifications or work under the terms of Section 1 ;above, provided that you also meet all of these conditions: ; ; a) You must cause the modified files to carry prominent notices ; stating that you changed the files and the date of any change. ; ; b) You must cause any work that you distribute or publish, that in ; whole or in part contains or is derived from the Program or any ; part thereof, to be licensed as a whole at no charge to all third ; parties under the terms of this License. ; ; c) If the modified program normally reads commands interactively ; when run, you must cause it, when started running for such ; interactive use in the most ordinary way, to print or display an ; announcement including an appropriate copyright notice and a ; notice that there is no warranty (or else, saying that you provide ; a warranty) and that users may redistribute the program under ; these conditions, and telling the user how to view a copy of this ; License. (Exception: if the Program itself is interactive but ; does not normally print such an announcement, your work based on ; the Program is not required to print an announcement.) ; ;These requirements apply to the modified work as a whole. If ;identifiable sections of that work are not derived from the Program, ;and can be reasonably considered independent and separate works in ;themselves, then this License, and its terms, do not apply to those ;sections when you distribute them as separate works. But when you ;distribute the same sections as part of a whole which is a work based ;on the Program, the distribution of the whole must be on the terms of ;this License, whose permissions for other licensees extend to the ;entire whole, and thus to each and every part regardless of who wrote it. ; ;Thus, it is not the intent of this section to claim rights or contest ;your rights to work written entirely by you; rather, the intent is to ;exercise the right to control the distribution of derivative or ;collective works based on the Program. ; ;In addition, mere aggregation of another work not based on the Program ;with the Program (or with a work based on the Program) on a volume of ;a storage or distribution medium does not bring the other work under ;the scope of this License. ; ; 3. You may copy and distribute the Program (or a work based on it, ;under Section 2) in object code or executable form under the terms of ;Sections 1 and 2 above provided that you also do one of the following: ; ; a) Accompany it with the complete corresponding machine-readable ; source code, which must be distributed under the terms of Sections ; 1 and 2 above on a medium customarily used for software interchange; or, ; ; b) Accompany it with a written offer, valid for at least three ; years, to give any third party, for a charge no more than your ; cost of physically performing source distribution, a complete ; machine-readable copy of the corresponding source code, to be ; distributed under the terms of Sections 1 and 2 above on a medium ; customarily used for software interchange; or, ; ; c) Accompany it with the information you received as to the offer ; to distribute corresponding source code. (This alternative is ; allowed only for noncommercial distribution and only if you ; received the program in object code or executable form with such ; an offer, in accord with Subsection b above.) ; ;The source code for a work means the preferred form of the work for ;making modifications to it. For an executable work, complete source ;code means all the source code for all modules it contains, plus any ;associated interface definition files, plus the scripts used to ;control compilation and installation of the executable. However, as a ;special exception, the source code distributed need not include ;anything that is normally distributed (in either source or binary ;form) with the major components (compiler, kernel, and so on) of the ;operating system on which the executable runs, unless that component ;itself accompanies the executable. ; ;If distribution of executable or object code is made by offering ;access to copy from a designated place, then offering equivalent ;access to copy the source code from the same place counts as ;distribution of the source code, even though third parties are not ;compelled to copy the source along with the object code. ; ; 4. You may not copy, modify, sublicense, or distribute the Program ;except as expressly provided under this License. Any attempt ;otherwise to copy, modify, sublicense or distribute the Program is ;void, and will automatically terminate your rights under this License. ;However, parties who have received copies, or rights, from you under ;this License will not have their licenses terminated so long as such ;parties remain in full compliance. ; ; 5. You are not required to accept this License, since you have not ;signed it. However, nothing else grants you permission to modify or ;distribute the Program or its derivative works. These actions are ;prohibited by law if you do not accept this License. Therefore, by ;modifying or distributing the Program (or any work based on the ;Program), you indicate your acceptance of this License to do so, and ;all its terms and conditions for copying, distributing or modifying ;the Program or works based on it. ; ; 6. Each time you redistribute the Program (or any work based on the ;Program), the recipient automatically receives a license from the ;original licensor to copy, distribute or modify the Program subject to ;these terms and conditions. You may not impose any further ;restrictions on the recipients' exercise of the rights granted herein. ;You are not responsible for enforcing compliance by third parties to ;this License. ; ; 7. If, as a consequence of a court judgment or allegation of patent ;infringement or for any other reason (not limited to patent issues), ;conditions are imposed on you (whether by court order, agreement or ;otherwise) that contradict the conditions of this License, they do not ;excuse you from the conditions of this License. If you cannot ;distribute so as to satisfy simultaneously your obligations under this ;License and any other pertinent obligations, then as a consequence you ;may not distribute the Program at all. For example, if a patent ;license would not permit royalty-free redistribution of the Program by ;all those who receive copies directly or indirectly through you, then ;the only way you could satisfy both it and this License would be to ;refrain entirely from distribution of the Program. ; ;If any portion of this section is held invalid or unenforceable under ;any particular circumstance, the balance of the section is intended to ;apply and the section as a whole is intended to apply in other ;circumstances. ; ;It is not the purpose of this section to induce you to infringe any ;patents or other property right claims or to contest validity of any ;such claims; this section has the sole purpose of protecting the ;integrity of the free software distribution system, which is ;implemented by public license practices. Many people have made ;generous contributions to the wide range of software distributed ;through that system in reliance on consistent application of that ;system; it is up to the author/donor to decide if he or she is willing ;to distribute software through any other system and a licensee cannot ;impose that choice. ; ;This section is intended to make thoroughly clear what is believed to ;be a consequence of the rest of this License. ; ; 8. If the distribution and/or use of the Program is restricted in ;certain countries either by patents or by copyrighted interfaces, the ;original copyright holder who places the Program under this License ;may add an explicit geographical distribution limitation excluding ;those countries, so that distribution is permitted only in or among ;countries not thus excluded. In such case, this License incorporates ;the limitation as if written in the body of this License. ; ; 9. The Free Software Foundation may publish revised and/or new versions ;of the General Public License from time to time. Such new versions will ;be similar in spirit to the present version, but may differ in detail to ;address new problems or concerns. ; ;Each version is given a distinguishing version number. If the Program ;specifies a version number of this License which applies to it and "any ;later version", you have the option of following the terms and conditions ;either of that version or of any later version published by the Free ;Software Foundation. If the Program does not specify a version number of ;this License, you may choose any version ever published by the Free Software ;Foundation. ; ; 10. If you wish to incorporate parts of the Program into other free ;programs whose distribution conditions are different, write to the author ;to ask for permission. For software which is copyrighted by the Free ;Software Foundation, write to the Free Software Foundation; we sometimes ;make exceptions for this. Our decision will be guided by the two goals ;of preserving the free status of all derivatives of our free software and ;of promoting the sharing and reuse of software generally. ; ; NO WARRANTY ; ; 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY ;FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN ;OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES ;PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED ;OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ;MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS ;TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE ;PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, ;REPAIR OR CORRECTION. ; ; 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING ;WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR ;REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, ;INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING ;OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED ;TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY ;YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER ;PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE ;POSSIBILITY OF SUCH DAMAGES. ; ; END OF TERMS AND CONDITIONS **************************************************************** * * Function Pointer Table (FPT) * * This table is required by the Tool Locator. It must be at * the start of the file. * **************************************************************** * * case on * state struct parameters count gequ 0 count0 gequ 0 count1 gequ 4 abcd gequ 8 abcd0 gequ 8 abcd1 gequ 12 abcd2 gequ 16 abcd3 gequ 20 buf gequ 24 * T Computation T1 gequ $d76aa478 T2 gequ $e8c7b756 T3 gequ $242070db T4 gequ $c1bdceee T5 gequ $f57c0faf T6 gequ $4787c62a T7 gequ $a8304613 T8 gequ $fd469501 T9 gequ $698098d8 T10 gequ $8b44f7af T11 gequ $ffff5bb1 T12 gequ $895cd7be T13 gequ $6b901122 T14 gequ $fd987193 T15 gequ $a679438e T16 gequ $49b40821 T17 gequ $f61e2562 T18 gequ $c040b340 T19 gequ $265e5a51 T20 gequ $e9b6c7aa T21 gequ $d62f105d T22 gequ $02441453 T23 gequ $d8a1e681 T24 gequ $e7d3fbc8 T25 gequ $21e1cde6 T26 gequ $c33707d6 T27 gequ $f4d50d87 T28 gequ $455a14ed T29 gequ $a9e3e905 T30 gequ $fcefa3f8 T31 gequ $676f02d9 T32 gequ $8d2a4c8a T33 gequ $fffa3942 T34 gequ $8771f681 T35 gequ $6d9d6122 T36 gequ $fde5380c T37 gequ $a4beea44 T38 gequ $4bdecfa9 T39 gequ $f6bb4b60 T40 gequ $bebfbc70 T41 gequ $289b7ec6 T42 gequ $eaa127fa T43 gequ $d4ef3085 T44 gequ $04881d05 T45 gequ $d9d4d039 T46 gequ $e6db99e5 T47 gequ $1fa27cf8 T48 gequ $c4ac5665 T49 gequ $f4292244 T50 gequ $432aff97 T51 gequ $ab9423a7 T52 gequ $fc93a039 T53 gequ $655b59c3 T54 gequ $8f0ccc92 T55 gequ $ffeff47d T56 gequ $85845dd1 T57 gequ $6fa87e4f T58 gequ $fe2ce6e0 T59 gequ $a3014314 T60 gequ $4e0811a1 T61 gequ $f7537e82 T62 gequ $bd3af235 T63 gequ $2ad7d2bb T64 gequ $eb86d391 FPT data count equ 14 function number for the highest numbered ! tool call dc i4'count+1' number of routines + 1 dc a4'mdBootInit-1' required functions dc a4'mdStartUp-1' dc a4'mdShutDown-1' dc a4'mdVersion-1' dc a4'mdReset-1' dc a4'mdStatus-1' dc a4'Null-1' reserved functions dc a4'Null-1' dc a4'md5_init-1' user functions dc a4'md5_append-1' dc a4'md5_finish-1' dc a4'md4_init-1' dc a4'md4_append-1' dc a4'md4_finish-1' end **************************************************************** * * Common - common data * **************************************************************** * Common data ; ; Constants ; false equ 0 boolean constant true equ 1 boolean constant toolVersion equ $0102 tool version number 1.0.2 active dc i2'0' end **************************************************************** * * Null - Called for required tool functions that don't do * anything * * BootInit - Required function; called at boot or load time * Reset - Required function; called during a system reset * * Outputs: * C - clear, indicating no error * A - 0, indicating no error * **************************************************************** * Null start mdBootInit entry mdReset entry clc no error lda #0 error code rtl end **************************************************************** * * Startup - Required function; called when the application * starts the tool * * Outputs: * C - clear, indicating no error * A - 0, indicating no error * **************************************************************** * mdStartUp start using Common lda #true active = true sta >active clc no error lda #0 error code rtl end **************************************************************** * * Shutdown - Required function; called when the application * shuts down the tool * * Outputs: * C - clear, indicating no error * A - 0, indicating no error * **************************************************************** * mdShutDown start using Common lda #false active = false sta >active clc no error lda #0 error code rtl end **************************************************************** * * Status - Required function; tells if the tool is active * * Outputs: * C - clear, indicating no error * A - 0, indicating no error * toolStatus - true if the tool is started, else false * **************************************************************** * mdStatus start using Common toolStatus equ 7 stack offset for toolStatus return value lda >active toolStatus = status sta toolStatus,S clc no error lda #0 error code rtl end **************************************************************** * * Version - Required function; returns the tool version * * Outputs: * C - clear, indicating no error * A - 0, indicating no error * outVersion - tool version number * **************************************************************** * mdVersion start using Common RTL1 equ 1 RTL2 equ RTL1+3 outVersion equ RTL2+3 stack offset for version return value lda #toolVersion version = toolVersion sta outVersion,S clc no error lda #0 error code rtl end md5_init start md4_init entry Using Common directPageOnStack equ 2 ; number of bytes from a phd ; state pointer - 4 bytes ; RTL2 - 3 bytes ; RTL1 - 3 bytes ; <- SP before phd ; phd - 2 bytes ; <- SP after phd RTL1 equ 1+directPageOnStack RTL2 equ RTL1+3 state equ RTL2+3 outputSpace equ state+4 (if there was a return value) inputsize equ outputSpace-state phd set up our direct page tsc tcd lda >active jeq clean_up lda #0 sta [state] ldy #count0+2 sta [state],y ldy #count1 sta [state],y ldy #count1+2 sta [state],y ldy #abcd0 lda #$2301 sta [state],y ldy #abcd0+2 lda #$6745 sta [state],y ldy #abcd1 lda #$ab89 sta [state],y ldy #abcd1+2 lda #$efcd sta [state],y ldy #abcd2 lda #$dcfe sta [state],y ldy #abcd2+2 lda #$98ba sta [state],y ldy #abcd3 lda #$5476 sta [state],y ldy #abcd3+2 lda #$1032 sta [state],y clean_up anop ; pop the input & restore caller's DP lda RTL1+4 sta outputSpace-2 lda RTL1+2 sta outputSpace-4 lda RTL1 sta outputSpace-6 pld tsc clc adc #inputsize tcs clc lda #0 rtl end md5_append start Using Common directPageOnStack equ 2 ; number of bytes from a phd RTL1 equ 1+directPageOnStack RTL2 equ RTL1+3 nbytes equ RTL2+3 data equ nbytes+4 pms equ data+4 outputSpace equ pms+4 (if there was a return value) inputsize equ outputSpace-nbytes phd set up our direct page tsc tcd lda >active jeq clean_up pei pms+2 pei pms pei data+2 pei data pei nbytes+2 pei nbytes jsl >md5_append2 clean_up anop ; pop the input & restore caller's DP lda RTL1+4 sta outputSpace-2 lda RTL1+2 sta outputSpace-4 lda RTL1 sta outputSpace-6 pld tsc clc adc #inputsize tcs clc lda #0 rtl end md5_append2 start Using Common directPageOnStack equ 2 ; number of bytes from a phd ; pms pointer - 4 bytes ; data pointer - 4 bytes ; number bytes - 4 bytes ; RTL - 3 bytes ; <- SP before phd ; phd - 2 bytes ; <- SP after phd ; subroutine direct page space - 4 bytes p equ 1 dpEnd equ p+4 RTL equ dpEnd+directPageOnStack nbytes equ RTL+3 data equ nbytes+4 pms equ data+4 outputSpace equ pms+4 (if there was a return value) inputsize equ outputSpace-nbytes dpsize equ dpEnd-p phd set up our direct page tsc sec sbc #dpsize tcs tcd ; if (nbytes <= 0) return; lda nbytes+2 jmi clean_up ora nbytes jeq clean_up ; *p = data; lda data sta p lda data+2 sta p+2 ; left = nbytes lda nbytes sta >left lda nbytes+2 sta >left+2 ; offset = (pms->count[0] >> 3) & 63; ldy #count0+2 lda [pms],y lsr a sta >temp lda [pms] ror a sta >offset lda >temp lsr a sta >temp lda >offset ror a sta >offset lda >temp lsr a sta >temp lda >offset ror a and #63 sta >offset ; nbits = nbytes << 3; lda nbytes asl a sta >nbits lda nbytes+2 rol a sta >nbits+2 lda >nbits asl a sta >nbits lda >nbits+2 rol a sta >nbits+2 lda >nbits asl a sta >nbits lda >nbits+2 rol a sta >nbits+2 ; pms->count[1] += nbytes >> 29; lda nbytes+2 lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a clc ldy #count1 adc [pms],y sta [pms],y lda #0 ldy #count1+2 adc [pms],y sta [pms],y ; pms->count[0] += nbits; lda [pms] clc adc >nbits sta [pms] ldy #count0+2 lda [pms],y adc >nbits+2 sta [pms],y ; if (pms->count[0] < nbits) ldy #count0+2 lda [pms],y cmp >nbits+2 bcc do_if_true_1 beq do_check_lsw_1 bcs process1stBlock do_check_lsw_1 anop lda [pms] cmp >nbits bcs process1stBlock do_if_true_1 anop ; pms->count[1]++; ldy #count1 lda [pms],y clc adc #1 sta [pms],y ldy #count1+2 lda [pms],y adc #0 sta [pms],y process1stBlock anop ; if (offset) lda >offset jeq processFullBlock ; copy = (offset + nbytes > 64 ? 64 - offset : nbytes; lda >offset clc adc nbytes sta >temp lda #0 adc nbytes+2 bne ternary_true_1 lda >temp cmp #65 bcc ternary_false_1 ternary_true_1 anop lda #64 sec sbc >offset sta >copy lda #0 sta >copy+2 bra ternary_done_1 ternary_false_1 anop lda nbytes sta >copy lda nbytes+2 sta >copy+2 ternary_done_1 anop ; memcpy(pms->buf+offset,p , copy); pei p+2 pei p lda pms clc adc #buf tax lda pms+2 clc adc #0 sta >temp txa clc adc >offset tax lda >temp clc adc #0 pha phx lda >copy+2 pha lda >copy pha ldx #$2b02 _BlockMove jsl >$e10000 ; if (offset + copy < 64) return; lda >offset clc adc >copy sta >temp lda #0 adc >copy+2 bne do_if_false_2 lda >temp cmp #64 bcs do_if_false_2 brl clean_up do_if_false_2 anop ; p+= copy; lda p clc adc >copy sta p lda p+2 adc >copy+2 sta p+2 ; left-=copy; lda >left sec sbc >copy sta >left lda >left+2 sbc >copy+2 sta >left+2 ; md5_process(pms,pms->buf); pei pms+2 pei pms lda pms clc adc #buf tax lda pms+2 adc #0 pha phx jsl >md5_process processFullBlock anop ; for (; left >= 64; p+=64, left -= 64) md5_process(pms,p); lda >left+2 bne in_forloop_1 lda >left cmp #64 jcc processFinalBlock in_forloop_1 anop pei pms+2 pei pms pei p+2 pei p jsl >md5_process lda p clc adc #64 sta p lda p+2 adc #0 sta p+2 lda >left sec sbc #64 sta >left lda >left+2 sbc #0 sta >left+2 bra processFullBlock processFinalBlock anop ; if (left) memcpy(pms->buf,p,left); lda >left ora >left+2 beq clean_up pei p+2 pei p lda pms clc adc #buf tax lda pms+2 clc adc #0 pha phx lda >left+2 pha lda >left pha ldx #$2b02 _BlockMove jsl >$e10000 clean_up anop ; pop the input & restore caller's DP lda RTL+1 sta outputSpace-2 lda RTL sta outputSpace-3 ; pld lda dpEnd tcd ; direct page is not at top of stack tsc clc adc #inputsize+dpsize+directPageonStack <-- not sure why this isn't working? ; adc #inputsize tcs rtl temp ds 2 left ds 4 offset ds 2 nbits ds 4 copy ds 4 end md5_process start Using Common directPageOnStack equ 2 ; number of bytes from a phd ; pms pointer - 4 bytes ; data pointer - 4 bytes ; number bytes - 4 bytes ; RTL - 3 bytes ; <- SP before phd ; phd - 2 bytes ; <- SP after phd ; subroutine direct page space - 4 bytes dpStart equ 1 X equ dpStart dpEnd equ X+4 RTL equ dpEnd+directPageOnStack data equ RTL+3 pms equ data+4 outputSpace equ pms+4 (if there was a return value) inputsize equ outputSpace-data dpsize equ dpEnd-dpStart phd set up our direct page tsc sec sbc #dpsize tcd tcs ; a=pms->abcd[0]; b=pms->abcd[1]; c=pms->abcd[2]; d=pms->abcd[3] ldy #abcd0 lda [pms],y sta >a_ ldy #abcd0+2 lda [pms],y sta >a_+2 ldy #abcd1 lda [pms],y sta >b_ ldy #abcd1+2 lda [pms],y sta >b_+2 ldy #abcd2 lda [pms],y sta >c_ ldy #abcd2+2 lda [pms],y sta >c_+2 ldy #abcd3 lda [pms],y sta >d_ ldy #abcd3+2 lda [pms],y sta >d_+2 ; X = data lda data sta X lda data+2 sta X+2 ; round 1 ; SET(a, b, c, d, 0, 7, T1); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 0 pea 7 pea T1|-$10 pea T1 jsr md5_set ; SET(d, a, b, c, 1, 12, T2); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 1 pea 12 pea T2|-$10 pea T2 jsr md5_set ; SET(c, d, a, b, 2, 17, T3); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 2 pea 17 pea T3|-$10 pea T3 jsr md5_set ; SET(b, c, d, a, 3, 22, T4); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 3 pea 22 pea T4|-$10 pea T4 jsr md5_set ; SET(a, b, c, d, 4, 7, T5); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 4 pea 7 pea T5|-$10 pea T5 jsr md5_set ; SET(d, a, b, c, 5, 12, T6); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 5 pea 12 pea T6|-$10 pea T6 jsr md5_set ; SET(c, d, a, b, 6, 17, T7); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 6 pea 17 pea T7|-$10 pea T7 jsr md5_set ; SET(b, c, d, a, 7, 22, T8); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 7 pea 22 pea T8|-$10 pea T8 jsr md5_set ; SET(a, b, c, d, 8, 7, T9); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 8 pea 7 pea T9|-$10 pea T9 jsr md5_set ; SET(d, a, b, c, 9, 12, T10); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 9 pea 12 pea T10|-$10 pea T10 jsr md5_set ; SET(c, d, a, b, 10, 17, T11); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 10 pea 17 pea T11|-$10 pea T11 jsr md5_set ; SET(b, c, d, a, 11, 22, T12); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 11 pea 22 pea T12|-$10 pea T12 jsr md5_set ; SET(a, b, c, d, 12, 7, T13); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 12 pea 7 pea T13|-$10 pea T13 jsr md5_set ; SET(d, a, b, c, 13, 12, T14); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 13 pea 12 pea T14|-$10 pea T14 jsr md5_set ; SET(c, d, a, b, 14, 17, T15); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 14 pea 17 pea T15|-$10 pea T15 jsr md5_set ; SET(b, c, d, a, 15, 22, T16); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 15 pea 22 pea T16|-$10 pea T16 jsr md5_set ; round2 ; SET(a, b, c, d, 1, 5, T17); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 1 pea 5 pea T17|-$10 pea T17 jsr md5_set2 ; SET(d, a, b, c, 6, 9, T18); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 6 pea 9 pea T18|-$10 pea T18 jsr md5_set2 ; SET(c, d, a, b, 11, 14, T19); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 11 pea 14 pea T19|-$10 pea T19 jsr md5_set2 ; SET(b, c, d, a, 0, 20, T20); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 0 pea 20 pea T20|-$10 pea T20 jsr md5_set2 ; SET(a, b, c, d, 5, 5, T21); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 5 pea 5 pea T21|-$10 pea T21 jsr md5_set2 ; SET(d, a, b, c, 10, 9, T22); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 10 pea 9 pea T22|-$10 pea T22 jsr md5_set2 ; SET(c, d, a, b, 15, 14, T23); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 15 pea 14 pea T23|-$10 pea T23 jsr md5_set2 ; SET(b, c, d, a, 4, 20, T24); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 4 pea 20 pea T24|-$10 pea T24 jsr md5_set2 ; SET(a, b, c, d, 9, 5, T25); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 9 pea 5 pea T25|-$10 pea T25 jsr md5_set2 ; SET(d, a, b, c, 14, 9, T26); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 14 pea 9 pea T26|-$10 pea T26 jsr md5_set2 ; SET(c, d, a, b, 3, 14, T27); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 3 pea 14 pea T27|-$10 pea T27 jsr md5_set2 ; SET(b, c, d, a, 8, 20, T28); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 8 pea 20 pea T28|-$10 pea T28 jsr md5_set2 ; SET(a, b, c, d, 13, 5, T29); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 13 pea 5 pea T29|-$10 pea T29 jsr md5_set2 ; SET(d, a, b, c, 2, 9, T30); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 2 pea 9 pea T30|-$10 pea T30 jsr md5_set2 ; SET(c, d, a, b, 7, 14, T31); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 7 pea 14 pea T31|-$10 pea T31 jsr md5_set2 ; SET(b, c, d, a, 12, 20, T32); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 12 pea 20 pea T32|-$10 pea T32 jsr md5_set2 ; round3 ; SET(a, b, c, d, 5, 4, T33); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 5 pea 4 pea T33|-$10 pea T33 jsr md5_set3 ; SET(d, a, b, c, 8, 11, T34); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 8 pea 11 pea T34|-$10 pea T34 jsr md5_set3 ; SET(c, d, a, b, 11, 16, T35); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 11 pea 16 pea T35|-$10 pea T35 jsr md5_set3 ; SET(b, c, d, a, 14, 23, T36); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 14 pea 23 pea T36|-$10 pea T36 jsr md5_set3 ; SET(a, b, c, d, 1, 4, T37); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 1 pea 4 pea T37|-$10 pea T37 jsr md5_set3 ; SET(d, a, b, c, 4, 11, T38); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 4 pea 11 pea T38|-$10 pea T38 jsr md5_set3 ; SET(c, d, a, b, 7, 16, T39); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 7 pea 16 pea T39|-$10 pea T39 jsr md5_set3 ; SET(b, c, d, a, 10, 23, T40); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 10 pea 23 pea T40|-$10 pea T40 jsr md5_set3 ; SET(a, b, c, d, 13, 4, T41); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 13 pea 4 pea T41|-$10 pea T41 jsr md5_set3 ; SET(d, a, b, c, 0, 11, T42); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 0 pea 11 pea T42|-$10 pea T42 jsr md5_set3 ; SET(c, d, a, b, 3, 16, T43); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 3 pea 16 pea T43|-$10 pea T43 jsr md5_set3 ; SET(b, c, d, a, 6, 23, T44); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 6 pea 23 pea T44|-$10 pea T44 jsr md5_set3 ; SET(a, b, c, d, 9, 4, T45); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 9 pea 4 pea T45|-$10 pea T45 jsr md5_set3 ; SET(d, a, b, c, 12, 11, T46); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 12 pea 11 pea T46|-$10 pea T46 jsr md5_set3 ; SET(c, d, a, b, 15, 16, T47); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 15 pea 16 pea T47|-$10 pea T47 jsr md5_set3 ; SET(b, c, d, a, 2, 23, T48); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 2 pea 23 pea T48|-$10 pea T48 jsr md5_set3 ; round4 ; SET(a, b, c, d, 0, 6, T49); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 0 pea 6 pea T49|-$10 pea T49 jsr md5_set4 ; SET(d, a, b, c, 7, 10, T50); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 7 pea 10 pea T50|-$10 pea T50 jsr md5_set4 ; SET(c, d, a, b, 14, 15, T51); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 14 pea 15 pea T51|-$10 pea T51 jsr md5_set4 ; SET(b, c, d, a, 5, 21, T52); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 5 pea 21 pea T52|-$10 pea T52 jsr md5_set4 ; SET(a, b, c, d, 12, 6, T53); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 12 pea 6 pea T53|-$10 pea T53 jsr md5_set4 ; SET(d, a, b, c, 3, 10, T54); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 3 pea 10 pea T54|-$10 pea T54 jsr md5_set4 ; SET(c, d, a, b, 10, 15, T55); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 10 pea 15 pea T55|-$10 pea T55 jsr md5_set4 ; SET(b, c, d, a, 1, 21, T56); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 1 pea 21 pea T56|-$10 pea T56 jsr md5_set4 ; SET(a, b, c, d, 8, 6, T57); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 8 pea 6 pea T57|-$10 pea T57 jsr md5_set4 ; SET(d, a, b, c, 15, 10, T58); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 15 pea 10 pea T58|-$10 pea T58 jsr md5_set4 ; SET(c, d, a, b, 6, 15, T59); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 6 pea 15 pea T59|-$10 pea T59 jsr md5_set4 ; SET(b, c, d, a, 13, 21, T60); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 13 pea 21 pea T60|-$10 pea T60 jsr md5_set4 ; SET(a, b, c, d, 4, 6, T61); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 4 pea 6 pea T61|-$10 pea T61 jsr md5_set4 ; SET(d, a, b, c, 11, 10, T62); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 11 pea 10 pea T62|-$10 pea T62 jsr md5_set4 ; SET(c, d, a, b, 2, 15, T63); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 2 pea 15 pea T63|-$10 pea T63 jsr md5_set4 ; SET(b, c, d, a, 9, 21, T64); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 9 pea 21 pea T64|-$10 pea T64 jsr md5_set4 ; pms->abcd[0] += a; ldy #abcd0 lda [pms],y clc adc >a_ sta [pms],y ldy #abcd0+2 lda [pms],y adc >a_+2 sta [pms],y ; pms->abcd[1] += b; ldy #abcd1 lda [pms],y clc adc >b_ sta [pms],y ldy #abcd1+2 lda [pms],y adc >b_+2 sta [pms],y ; pms->abcd[2] += c; ldy #abcd2 lda [pms],y clc adc >c_ sta [pms],y ldy #abcd2+2 lda [pms],y adc >c_+2 sta [pms],y ; pms->abcd[3] += d; ldy #abcd3 lda [pms],y clc adc >d_ sta [pms],y ldy #abcd3+2 lda [pms],y adc >d_+2 sta [pms],y clean_up anop ; pop the input & restore caller's DP lda RTL+1 sta outputSpace-2 lda RTL sta outputSpace-3 ; pld lda dpEnd tcd ; direct page is not at top of stack tsc clc adc #inputsize+dpsize+directPageonStack <-- not sure why this isn't working? tcs rtl md5_set anop set_phd equ 1 set_rts equ set_phd+2 set_t equ set_rts+2 set_s equ set_t+4 set_k equ set_s+2 set_d equ set_k+2 set_c equ set_d+4 set_b equ set_c+4 set_a equ set_b+4 set_stackEnd equ set_a+4 phd tsc tcd ; #define SET(a,b,c,d,k,s,Ti) t=a+F(b,c,d)+X[k]+T1 a=ROTATE_LEFT(t,s)+b pha ; space for return value pha pei set_b+2 pei set_b pei set_c+2 pei set_c pei set_d+2 pei set_d jsr md5_f pla sta >t pla sta >t+2 lda set_k asl a ; multiply by 4 asl a tay lda [set_stackEnd+X-1],y ; access X in direct page from clc ; routine calling this one adc >t sta >t iny iny lda [set_stackEnd+X-1],y adc >t+2 sta >t+2 clc lda >t adc set_t sta >t lda >t+2 adc set_t+2 sta >t+2 clc lda >t adc [set_a] sta >t lda >t+2 ldy #2 adc [set_a],y sta >t+2 pha ; space for return value pha lda >t+2 pha lda >t pha pei set_s jsr md5_rotate_left pla clc adc [set_b] sta [set_a] pla ldy #2 adc [set_b],y sta [set_a],y lda set_rts sta set_stackEnd-2 pld tsc clc adc #set_stackEnd-set_t tcs rts md5_set2 anop set2_phd equ 1 set2_rts equ set2_phd+2 set2_t equ set2_rts+2 set2_s equ set2_t+4 set2_k equ set2_s+2 set2_d equ set2_k+2 set2_c equ set2_d+4 set2_b equ set2_c+4 set2_a equ set2_b+4 set2_stackEnd equ set2_a+4 phd tsc tcd ; #define SET(a,b,c,d,k,s,Ti) t=a+G(b,c,d)+X[k]+T1 a=ROTATE_LEFT(t,s)+b pha ; space for return value pha pei set2_b+2 pei set2_b pei set2_c+2 pei set2_c pei set2_d+2 pei set2_d jsr md5_g pla sta >t pla sta >t+2 lda set2_k asl a ; multiply by 4 asl a tay lda [set2_stackEnd+X-1],y ; access X in direct page from clc ; routine calling this one adc >t sta >t iny iny lda [set2_stackEnd+X-1],y adc >t+2 sta >t+2 clc lda >t adc set2_t sta >t lda >t+2 adc set2_t+2 sta >t+2 clc lda >t adc [set2_a] sta >t lda >t+2 ldy #2 adc [set2_a],y sta >t+2 pha ; space for return value pha lda >t+2 pha lda >t pha pei set2_s jsr md5_rotate_left pla clc adc [set2_b] sta [set2_a] pla ldy #2 adc [set2_b],y sta [set2_a],y lda set2_rts sta set2_stackEnd-2 pld tsc clc adc #set2_stackEnd-set2_t tcs rts md5_set3 anop set3_phd equ 1 set3_rts equ set3_phd+2 set3_t equ set3_rts+2 set3_s equ set3_t+4 set3_k equ set3_s+2 set3_d equ set3_k+2 set3_c equ set3_d+4 set3_b equ set3_c+4 set3_a equ set3_b+4 set3_stackEnd equ set3_a+4 phd tsc tcd ; #define SET(a,b,c,d,k,s,Ti) t=a+H(b,c,d)+X[k]+T1 a=ROTATE_LEFT(t,s)+b pha ; space for return value pha pei set3_b+2 pei set3_b pei set3_c+2 pei set3_c pei set3_d+2 pei set3_d jsr md5_h pla sta >t pla sta >t+2 lda set3_k asl a ; multiply by 4 asl a tay lda [set3_stackEnd+X-1],y ; access X in direct page from clc ; routine calling this one adc >t sta >t iny iny lda [set3_stackEnd+X-1],y adc >t+2 sta >t+2 clc lda >t adc set3_t sta >t lda >t+2 adc set3_t+2 sta >t+2 clc lda >t adc [set3_a] sta >t lda >t+2 ldy #2 adc [set3_a],y sta >t+2 pha ; space for return value pha lda >t+2 pha lda >t pha pei set3_s jsr md5_rotate_left pla clc adc [set3_b] sta [set3_a] pla ldy #2 adc [set3_b],y sta [set3_a],y lda set3_rts sta set3_stackEnd-2 pld tsc clc adc #set3_stackEnd-set3_t tcs rts md5_set4 anop set4_phd equ 1 set4_rts equ set4_phd+2 set4_t equ set4_rts+2 set4_s equ set4_t+4 set4_k equ set4_s+2 set4_d equ set4_k+2 set4_c equ set4_d+4 set4_b equ set4_c+4 set4_a equ set4_b+4 set4_stackEnd equ set4_a+4 phd tsc tcd ; #define SET(a,b,c,d,k,s,Ti) t=a+I(b,c,d)+X[k]+T1 a=ROTATE_LEFT(t,s)+b pha ; space for return value pha pei set4_b+2 pei set4_b pei set4_c+2 pei set4_c pei set4_d+2 pei set4_d jsr md5_i pla sta >t pla sta >t+2 lda set4_k asl a ; multiply by 4 asl a tay lda [set4_stackEnd+X-1],y ; access X in direct page from clc ; routine calling this one adc >t sta >t iny iny lda [set4_stackEnd+X-1],y adc >t+2 sta >t+2 clc lda >t adc set4_t sta >t lda >t+2 adc set4_t+2 sta >t+2 clc lda >t adc [set4_a] sta >t lda >t+2 ldy #2 adc [set4_a],y sta >t+2 pha ; space for return value pha lda >t+2 pha lda >t pha pei set4_s jsr md5_rotate_left pla clc adc [set4_b] sta [set4_a] pla ldy #2 adc [set4_b],y sta [set4_a],y lda set4_rts sta set4_stackEnd-2 pld tsc clc adc #set4_stackEnd-set4_t tcs rts md5_f entry f_phd equ 1 f_rts equ f_phd+2 f_z equ f_rts+2 f_y equ f_z+4 f_x equ f_y+4 f_return equ f_x+4 f_stackEnd equ f_return+4 phd tsc tcd ; #define F(x,y,z) (((x) & (y)) | (~(x) & (z))) lda [f_x] and [f_y] tax ldy #2 lda [f_x],y and [f_y],y sta f_y+2 txa sta f_y lda [f_x] eor #$ffff and [f_z] ora f_y sta f_return lda [f_x],y eor #$ffff and [f_z],y ora f_y+2 sta f_return+2 lda f_rts sta f_return-2 pld tsc clc adc #f_return-f_z tcs rts md5_g anop g_phd equ 1 g_rts equ g_phd+2 g_z equ g_rts+2 g_y equ g_z+4 g_x equ g_y+4 g_return equ g_x+4 g_stackEnd equ g_return+4 phd tsc tcd ; #define G(x,y,z) (((x) & (z)) | ((y) & ~(z))) lda [g_x] and [g_z] tax ldy #2 lda [g_x],y and [g_z],y sta g_x+2 txa sta g_x lda [g_z] eor #$ffff and [g_y] ora g_x sta g_return lda [g_z],y eor #$ffff and [g_y],y ora g_x+2 sta g_return+2 lda g_rts sta g_return-2 pld tsc clc adc #g_return-g_z tcs rts md5_h entry h_phd equ 1 h_rts equ h_phd+2 h_z equ h_rts+2 h_y equ h_z+4 h_x equ h_y+4 h_return equ h_x+4 h_stackEnd equ h_return+4 phd tsc tcd ; #define H(x,y,z) ((x) ^ (y) ^ (z)) lda [h_x] eor [h_y] eor [h_z] sta h_return ldy #2 lda [h_x],y eor [h_y],y eor [h_z],y sta h_return+2 lda h_rts sta h_return-2 pld tsc clc adc #h_return-h_z tcs rts md5_i anop i_phd equ 1 i_rts equ i_phd+2 i_z equ i_rts+2 i_y equ i_z+4 i_x equ i_y+4 i_return equ i_x+4 i_stackEnd equ i_return+4 phd tsc tcd ; #define I(x,y,z) ((y) ^ ((x) | ~(z))) lda [h_z] eor #$ffff ora [h_x] eor [h_y] sta h_return ldy #2 lda [h_z],y eor #$ffff ora [h_x],y eor [h_y],y sta h_return+2 lda h_rts sta h_return-2 pld tsc clc adc #h_return-h_z tcs rts md5_rotate_left entry rl_phd equ 1 rl_rts equ rl_phd+2 rl_n equ rl_rts+2 rl_x equ rl_n+2 rl_return equ rl_x+4 rl_stackEnd equ rl_return+4 phd tsc tcd ; #define ROTATE_LEFT(x,n) (((x) << (n)) | ((x) >> (32 - (n)))) ldx rl_n rl_loop anop cpx #0 beq rl_loop_end lda rl_x asl a lda rl_x+2 rol a sta rl_x+2 lda rl_x rol a sta rl_x dex bra rl_loop rl_loop_end anop lda rl_x sta rl_return lda rl_x+2 sta rl_return+2 lda rl_rts sta rl_return-2 pld tsc clc adc #rl_return-rl_n tcs rts a_ ds 4 b_ ds 4 c_ ds 4 d_ ds 4 t ds 4 end md5_finish start Using Common directPageOnStack equ 2 ; number of bytes from a phd RTL1 equ 1+directPageOnStack RTL2 equ RTL1+3 digest equ RTL2+3 pms equ digest+4 outputSpace equ pms+4 (if there was a return value) inputsize equ outputSpace-digest phd set up our direct page tsc tcd lda >active jeq clean_up ; for (i=0; i < 8; ++i); ; data[i] = (pms->count[i >> 2] >> ((i & 3) << 3)); lda [pms] sta >data ldy #count0+2 lda [pms],y sta >data+2 ldy #count1 lda [pms],y sta >data+4 ldy #count1+2 lda [pms],y sta >data+6 ; md5_append(pms,pad, ((55 - (pms->count[0] >> 3)) & 63) +1); pei pms+2 pei pms pea pad|-$10 pea pad ldy #count0+2 lda [pms],y lsr a sta >temp+2 ldy #count0 lda [pms],y ror a sta >temp lda >temp+2 lsr a sta >temp+2 lda >temp ror a sta >temp lda >temp+2 lsr a sta >temp+2 lda >temp ror a sta >temp lda #55 sec sbc >temp and #63 clc adc #1 pea 0 pha jsl >md5_append2 ; md5_append(pms, data, 8); pei pms+2 pei pms pea data|-$10 pea data pea 0 pea 8 jsl >md5_append2 ; for ( i = 0; i < 16; ++i); ; digest[i] = (pms->abcd[i >> 2] >> ((i & 3) << 3)) ldy #abcd0 lda [pms],y sta [digest] ldy #abcd0+2 lda [pms],y ldy #2 sta [digest],y ldy #abcd1 lda [pms],y ldy #4 sta [digest],y ldy #abcd1+2 lda [pms],y ldy #6 sta [digest],y ldy #abcd2 lda [pms],y ldy #8 sta [digest],y ldy #abcd2+2 lda [pms],y ldy #10 sta [digest],y ldy #abcd3 lda [pms],y ldy #12 sta [digest],y ldy #abcd3+2 lda [pms],y ldy #14 sta [digest],y clean_up anop ; pop the input & restore caller's DP lda RTL1+4 sta outputSpace-2 lda RTL1+2 sta outputSpace-4 lda RTL1 sta outputSpace-6 pld tsc clc adc #inputsize tcs clc lda #0 rtl pad dc h'80' dc 63h'00' data ds 8 temp ds 4 end ; The only difference between md5_append and md4_append is the usage of ; the md4_append2 subroutine call. ; If you want to save code size, this can be optimized with a flag for ; md4 or md5. md4_append start Using Common directPageOnStack equ 2 ; number of bytes from a phd RTL1 equ 1+directPageOnStack RTL2 equ RTL1+3 nbytes equ RTL2+3 data equ nbytes+4 pms equ data+4 outputSpace equ pms+4 (if there was a return value) inputsize equ outputSpace-nbytes phd set up our direct page tsc tcd lda >active jeq clean_up pei pms+2 pei pms pei data+2 pei data pei nbytes+2 pei nbytes jsl >md4_append2 clean_up anop ; pop the input & restore caller's DP lda RTL1+4 sta outputSpace-2 lda RTL1+2 sta outputSpace-4 lda RTL1 sta outputSpace-6 pld tsc clc adc #inputsize tcs clc lda #0 rtl end ; The only difference between md5_append2 and md4_append2 is the usage of ; the md4_process subroutine call. ; If you want to save code size, this can be optimized with a flag for ; md4 or md5. md4_append2 start Using Common directPageOnStack equ 2 ; number of bytes from a phd ; pms pointer - 4 bytes ; data pointer - 4 bytes ; number bytes - 4 bytes ; RTL - 3 bytes ; <- SP before phd ; phd - 2 bytes ; <- SP after phd ; subroutine direct page space - 4 bytes p equ 1 dpEnd equ p+4 RTL equ dpEnd+directPageOnStack nbytes equ RTL+3 data equ nbytes+4 pms equ data+4 outputSpace equ pms+4 (if there was a return value) inputsize equ outputSpace-nbytes dpsize equ dpEnd-p phd set up our direct page tsc sec sbc #dpsize tcs tcd ; if (nbytes <= 0) return; lda nbytes+2 jmi clean_up ora nbytes jeq clean_up ; *p = data; lda data sta p lda data+2 sta p+2 ; left = nbytes lda nbytes sta >left lda nbytes+2 sta >left+2 ; offset = (pms->count[0] >> 3) & 63; ldy #count0+2 lda [pms],y lsr a sta >temp lda [pms] ror a sta >offset lda >temp lsr a sta >temp lda >offset ror a sta >offset lda >temp lsr a sta >temp lda >offset ror a and #63 sta >offset ; nbits = nbytes << 3; lda nbytes asl a sta >nbits lda nbytes+2 rol a sta >nbits+2 lda >nbits asl a sta >nbits lda >nbits+2 rol a sta >nbits+2 lda >nbits asl a sta >nbits lda >nbits+2 rol a sta >nbits+2 ; pms->count[1] += nbytes >> 29; lda nbytes+2 lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a clc ldy #count1 adc [pms],y sta [pms],y lda #0 ldy #count1+2 adc [pms],y sta [pms],y ; pms->count[0] += nbits; lda [pms] clc adc >nbits sta [pms] ldy #count0+2 lda [pms],y adc >nbits+2 sta [pms],y ; if (pms->count[0] < nbits) ldy #count0+2 lda [pms],y cmp >nbits+2 bcc do_if_true_1 beq do_check_lsw_1 bcs process1stBlock do_check_lsw_1 anop lda [pms] cmp >nbits bcs process1stBlock do_if_true_1 anop ; pms->count[1]++; ldy #count1 lda [pms],y clc adc #1 sta [pms],y ldy #count1+2 lda [pms],y adc #0 sta [pms],y process1stBlock anop ; if (offset) lda >offset jeq processFullBlock ; copy = (offset + nbytes > 64 ? 64 - offset : nbytes; lda >offset clc adc nbytes sta >temp lda #0 adc nbytes+2 bne ternary_true_1 lda >temp cmp #65 bcc ternary_false_1 ternary_true_1 anop lda #64 sec sbc >offset sta >copy lda #0 sta >copy+2 bra ternary_done_1 ternary_false_1 anop lda nbytes sta >copy lda nbytes+2 sta >copy+2 ternary_done_1 anop ; memcpy(pms->buf+offset,p , copy); pei p+2 pei p lda pms clc adc #buf tax lda pms+2 clc adc #0 sta >temp txa clc adc >offset tax lda >temp clc adc #0 pha phx lda >copy+2 pha lda >copy pha ldx #$2b02 _BlockMove jsl >$e10000 ; if (offset + copy < 64) return; lda >offset clc adc >copy sta >temp lda #0 adc >copy+2 bne do_if_false_2 lda >temp cmp #64 bcs do_if_false_2 brl clean_up do_if_false_2 anop ; p+= copy; lda p clc adc >copy sta p lda p+2 adc >copy+2 sta p+2 ; left-=copy; lda >left sec sbc >copy sta >left lda >left+2 sbc >copy+2 sta >left+2 ; md4_process(pms,pms->buf); pei pms+2 pei pms lda pms clc adc #buf tax lda pms+2 adc #0 pha phx jsl >md4_process processFullBlock anop ; for (; left >= 64; p+=64, left -= 64) md4_process(pms,p); lda >left+2 bne in_forloop_1 lda >left cmp #64 jcc processFinalBlock in_forloop_1 anop pei pms+2 pei pms pei p+2 pei p jsl >md4_process lda p clc adc #64 sta p lda p+2 adc #0 sta p+2 lda >left sec sbc #64 sta >left lda >left+2 sbc #0 sta >left+2 bra processFullBlock processFinalBlock anop ; if (left) memcpy(pms->buf,p,left); lda >left ora >left+2 beq clean_up pei p+2 pei p lda pms clc adc #buf tax lda pms+2 clc adc #0 pha phx lda >left+2 pha lda >left pha ldx #$2b02 _BlockMove jsl >$e10000 clean_up anop ; pop the input & restore caller's DP lda RTL+1 sta outputSpace-2 lda RTL sta outputSpace-3 ; pld lda dpEnd tcd ; direct page is not at top of stack tsc clc adc #inputsize+dpsize+directPageonStack <-- not sure why this isn't working? ; adc #inputsize tcs rtl temp ds 2 left ds 4 offset ds 2 nbits ds 4 copy ds 4 end ; md4_process has quite significant changes from md5_process. md4_process start Using Common directPageOnStack equ 2 ; number of bytes from a phd ; pms pointer - 4 bytes ; data pointer - 4 bytes ; number bytes - 4 bytes ; RTL - 3 bytes ; <- SP before phd ; phd - 2 bytes ; <- SP after phd ; subroutine direct page space - 4 bytes dpStart equ 1 X equ dpStart dpEnd equ X+4 RTL equ dpEnd+directPageOnStack data equ RTL+3 pms equ data+4 outputSpace equ pms+4 (if there was a return value) inputsize equ outputSpace-data dpsize equ dpEnd-dpStart phd set up our direct page tsc sec sbc #dpsize tcd tcs ; This section of code is the same as the md5 section ; a=pms->abcd[0]; b=pms->abcd[1]; c=pms->abcd[2]; d=pms->abcd[3] ldy #abcd0 lda [pms],y sta >a_ ldy #abcd0+2 lda [pms],y sta >a_+2 ldy #abcd1 lda [pms],y sta >b_ ldy #abcd1+2 lda [pms],y sta >b_+2 ldy #abcd2 lda [pms],y sta >c_ ldy #abcd2+2 lda [pms],y sta >c_+2 ldy #abcd3 lda [pms],y sta >d_ ldy #abcd3+2 lda [pms],y sta >d_+2 ; X = data lda data sta X lda data+2 sta X+2 ; This is where md4_process diverges significantly from md5_process ; round 1 ; SET(a, b, c, d, 0, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 0 pea 3 jsr md4_set ; SET(d, a, b, c, 1, 7); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 1 pea 7 jsr md4_set ; SET(c, d, a, b, 2, 11); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 2 pea 11 jsr md4_set ; SET(b, c, d, a, 3, 19); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 3 pea 19 jsr md4_set ; SET(a, b, c, d, 4, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 4 pea 3 jsr md4_set ; SET(d, a, b, c, 5, 7); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 5 pea 7 jsr md4_set ; SET(c, d, a, b, 6, 11); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 6 pea 11 jsr md4_set ; SET(b, c, d, a, 7, 19); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 7 pea 19 jsr md4_set ; SET(a, b, c, d, 8, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 8 pea 3 jsr md4_set ; SET(d, a, b, c, 9, 7); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 9 pea 7 jsr md4_set ; SET(c, d, a, b, 10, 11); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 10 pea 11 jsr md4_set ; SET(b, c, d, a, 11, 19); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 11 pea 19 jsr md4_set ; SET(a, b, c, d, 12, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 12 pea 3 jsr md4_set ; SET(d, a, b, c, 13, 7); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 13 pea 7 jsr md4_set ; SET(c, d, a, b, 14, 11); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 14 pea 11 jsr md4_set ; SET(b, c, d, a, 15, 19); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 15 pea 19 jsr md4_set ; round2 ; SET(a, b, c, d, 0, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 0 pea 3 jsr md4_set2 ; SET(d, a, b, c, 4, 5); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 4 pea 5 jsr md4_set2 ; SET(c, d, a, b, 8, 9); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 8 pea 9 jsr md4_set2 ; SET(b, c, d, a, 12, 13); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 12 pea 13 jsr md4_set2 ; SET(a, b, c, d, 1, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 1 pea 3 jsr md4_set2 ; SET(d, a, b, c, 5, 5); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 5 pea 5 jsr md4_set2 ; SET(c, d, a, b, 9, 9); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 9 pea 9 jsr md4_set2 ; SET(b, c, d, a, 13, 13); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 13 pea 13 jsr md4_set2 ; SET(a, b, c, d, 2, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 2 pea 3 jsr md4_set2 ; SET(d, a, b, c, 6, 5); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 6 pea 5 jsr md4_set2 ; SET(c, d, a, b, 10, 9); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 10 pea 9 jsr md4_set2 ; SET(b, c, d, a, 14, 13); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 14 pea 13 jsr md4_set2 ; SET(a, b, c, d, 3, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 3 pea 3 jsr md4_set2 ; SET(d, a, b, c, 7, 5); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 7 pea 5 jsr md4_set2 ; SET(c, d, a, b, 11, 9); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 11 pea 9 jsr md4_set2 ; SET(b, c, d, a, 15, 13); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 15 pea 13 jsr md4_set2 ; round3 ; SET(a, b, c, d, 0, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 0 pea 3 jsr md4_set3 ; SET(d, a, b, c, 8, 9); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 8 pea 9 jsr md4_set3 ; SET(c, d, a, b, 4, 11); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 4 pea 11 jsr md4_set3 ; SET(b, c, d, a, 12, 15); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 12 pea 15 jsr md4_set3 ; SET(a, b, c, d, 2, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 2 pea 3 jsr md4_set3 ; SET(d, a, b, c, 10, 9); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 10 pea 9 jsr md4_set3 ; SET(c, d, a, b, 6, 11); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 6 pea 11 jsr md4_set3 ; SET(b, c, d, a, 14, 15); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 14 pea 15 jsr md4_set3 ; SET(a, b, c, d, 1, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 1 pea 3 jsr md4_set3 ; SET(d, a, b, c, 9, 9); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 9 pea 9 jsr md4_set3 ; SET(c, d, a, b, 5, 11); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 5 pea 11 jsr md4_set3 ; SET(b, c, d, a, 13, 15); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 13 pea 15 jsr md4_set3 ; SET(a, b, c, d, 3, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 3 pea 3 jsr md4_set3 ; SET(d, a, b, c, 11, 9); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 11 pea 9 jsr md4_set3 ; SET(c, d, a, b, 7, 11); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 7 pea 11 jsr md4_set3 ; SET(b, c, d, a, 15, 15); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 15 pea 15 jsr md4_set3 ; This code is the same as md5_process and could be optimized. ; pms->abcd[0] += a; ldy #abcd0 lda [pms],y clc adc >a_ sta [pms],y ldy #abcd0+2 lda [pms],y adc >a_+2 sta [pms],y ; pms->abcd[1] += b; ldy #abcd1 lda [pms],y clc adc >b_ sta [pms],y ldy #abcd1+2 lda [pms],y adc >b_+2 sta [pms],y ; pms->abcd[2] += c; ldy #abcd2 lda [pms],y clc adc >c_ sta [pms],y ldy #abcd2+2 lda [pms],y adc >c_+2 sta [pms],y ; pms->abcd[3] += d; ldy #abcd3 lda [pms],y clc adc >d_ sta [pms],y ldy #abcd3+2 lda [pms],y adc >d_+2 sta [pms],y clean_up anop ; pop the input & restore caller's DP lda RTL+1 sta outputSpace-2 lda RTL sta outputSpace-3 ; pld lda dpEnd tcd ; direct page is not at top of stack tsc clc adc #inputsize+dpsize+directPageonStack <-- not sure why this isn't working? tcs rtl ; The following subroutines are slightly different from md5 md4_set anop set_phd equ 1 set_rts equ set_phd+2 set_s equ set_rts+2 set_k equ set_s+2 set_d equ set_k+2 set_c equ set_d+4 set_b equ set_c+4 set_a equ set_b+4 set_stackEnd equ set_a+4 phd tsc tcd ; #define SET(a,b,c,d,k,s) t=a+F(b,c,d)+X[k] a=ROTATE_LEFT(t,s) pha ; space for return value pha pei t pla sta >t+2 lda t sta >t iny iny lda [t+2 sta >t+2 clc lda >t adc [t lda >t+2 ldy #2 adc [t+2 pha ; space for return value pha lda >t+2 pha lda >t pha pei t pla sta >t+2 lda set2_k asl a ; multiply by 4 asl a tay lda [t sta >t iny iny lda [t+2 sta >t+2 clc lda >t adc #$7999 sta >t lda >t+2 adc #$5A82 sta >t+2 clc lda >t adc [t lda >t+2 ldy #2 adc [t+2 pha ; space for return value pha lda >t+2 pha lda >t pha pei t pla sta >t+2 lda set3_k asl a ; multiply by 4 asl a tay lda [t sta >t iny iny lda [t+2 sta >t+2 clc lda >t adc #$EBA1 sta >t lda >t+2 adc #$6ED9 sta >t+2 clc lda >t adc [t lda >t+2 ldy #2 adc [t+2 pha ; space for return value pha lda >t+2 pha lda >t pha pei active jeq clean_up ; for (i=0; i < 8; ++i); ; data[i] = (pms->count[i >> 2] >> ((i & 3) << 3)); lda [pms] sta >data ldy #count0+2 lda [pms],y sta >data+2 ldy #count1 lda [pms],y sta >data+4 ldy #count1+2 lda [pms],y sta >data+6 ; md4_append(pms,pad, ((55 - (pms->count[0] >> 3)) & 63) +1); pei pms+2 pei pms pea pad|-$10 pea pad ldy #count0+2 lda [pms],y lsr a sta >temp+2 ldy #count0 lda [pms],y ror a sta >temp lda >temp+2 lsr a sta >temp+2 lda >temp ror a sta >temp lda >temp+2 lsr a sta >temp+2 lda >temp ror a sta >temp lda #55 sec sbc >temp and #63 clc adc #1 pea 0 pha jsl >md4_append2 ; md4_append(pms, data, 8); pei pms+2 pei pms pea data|-$10 pea data pea 0 pea 8 jsl >md4_append2 ; for ( i = 0; i < 16; ++i); ; digest[i] = (pms->abcd[i >> 2] >> ((i & 3) << 3)) ldy #abcd0 lda [pms],y sta [digest] ldy #abcd0+2 lda [pms],y ldy #2 sta [digest],y ldy #abcd1 lda [pms],y ldy #4 sta [digest],y ldy #abcd1+2 lda [pms],y ldy #6 sta [digest],y ldy #abcd2 lda [pms],y ldy #8 sta [digest],y ldy #abcd2+2 lda [pms],y ldy #10 sta [digest],y ldy #abcd3 lda [pms],y ldy #12 sta [digest],y ldy #abcd3+2 lda [pms],y ldy #14 sta [digest],y clean_up anop ; pop the input & restore caller's DP lda RTL1+4 sta outputSpace-2 lda RTL1+2 sta outputSpace-4 lda RTL1 sta outputSpace-6 pld tsc clc adc #inputsize tcs clc lda #0 rtl pad dc h'80' dc 63h'00' data ds 8 temp ds 4 end