%!PS % Tearing Method Color Rework ezine % ======= % Don Lancaster % May 2017 % ====== % The tearing method is a classic and amazingly fast and easy way % to analyze any Apple II machine language program. % ====== % The Gonzo Utilities are to be run as a diskfile for the much shorter code here, % Distiller MUST be run from the command line as this or similar % //acrodist.exe" /F run % ======= % Uncomment and modify to use disk based Gonzo. ( or other disk access ) (C:/Users/Don/Desktop/Ghost/gonzo.psl) run % use internal % A tutorial can be found at http://www.tinaja.com/glib/gonzotut.pdf % Support: don@tinaja.com http://www.tinaja.com %%%%%%%%%%%%%% Tearing Support Files %%%%%%%%%%%% % ============== gonzo enhancements /webtintmat [ 0 1 5 {/a exch store 0 1 5 % webtint color array {/b exch store 0 1 5 {5 div b 5 div a 5 div} for }for } for ] def /setwebtint { abs cvi 216 cvi mod webtintmat % set 215 colors exch 3 mul 3 getinterval aload pop setrgbcolor} def /supercstroke { save /sssnap exch def /sscmd exch def mark 0 2 sscmd length 2 div cvi 1 sub 2 mul {/aposn exch def gsave sscmd aposn get setlinewidth sscmd aposn 1 add get setwebtint stroke grestore} for cleartomark sssnap restore newpath} def % =============== tearing specific common files % \261 em dash % \267 bullet % \274 ellipsis % \320 en dash /setuppage { grestore %% huh? gsave overflows at 80?? 50 20 10 setgrid {51 76 showgrid} if setpagefonts } store /evenheader { 3 string cvs /pagenum exch store font: 0 73 pagenum ( Enhancement 3) mergestr cl 1 setlinecap 0 72.2 mt 51 pr [0.7 126 0.45 212 ] supercstroke } store /oddheader { 3 string cvs /pagenum exch store font: 51 73 1 setlinecap (Tearing Into Machine Language Code ) pagenum mergestr cr 0 72.2 mt 51 pr [0.7 126 0.45 212 ] supercstroke } store /makeblue { mark 126 /setwebtint cvx ] cvx printlist exch 3 index exch put exch 1 add exch } store /makebrown { mark 44 /setwebtint cvx ] cvx printlist exch 3 index exch put exch 1 add exch } store /makeblack { mark 0 /setwebtint cvx ] cvx printlist exch 3 index exch put exch 1 add exch } store /makered { mark 5 /setwebtint cvx ] cvx printlist exch 3 index exch put exch 1 add exch } store /makeburple { mark 74 /setwebtint cvx ] cvx printlist exch 3 index exch put exch 1 add exch } store /setpagefonts { /cstretch 0.015 def /sstretch 0.015 def /font0 /StoneSans-Bold 2.0 gonzofont /font1 /StoneSans 0.95 gonzofont /font2 /StoneSans [0.95 0 0.25 0.95 0 0 ] gonzofont /font4 /StoneSans 0.85 gonzofont /font3 /StoneSans-Bold 0.95 gonzofont /font6 /StoneSans-Bold 0.85 gonzofont /font7 /StoneSans-Bold 1.05 gonzofont % subheaders /font8 /StoneSans-Bold [0.5 0 0 0.5 0 0] gonzofont /font9 /Courier-Bold 1 gonzofont /font; /ZapfDingbats [8 0 0 8 0 0 ] gonzofont /font: /Arial-ItalicMT 1.0 gonzofont /font- /StoneSans-Bold 1.75 gonzofont font1 /txtwide 35 store /yinc 1.2 store /kern 0.1 store /texttop 51 store /textleft 3 store /pm 1.5 store /amacro {(zy0) stringmacro /ypos ypos ypara add def} def % start drop cap /bmacro {(iFy1) stringmacro /ypos ypos ypara add def} def % finish drop cap } store %%%%%%%%%%%%%%%%%% jpeg inserter %%%%%%%%%%%%%%% /jpegimageprocwithlink { % hoffset voffset hres vres urlfrom urlto save /snap2 exch def /inurllink exch store % grab link filename /infilename exch store % grab passed pix file /photoscale exch store /vpixels exch store /hpixels exch store % (\nvpixels = )print vpixels == % (\nhpixels = )print hpixels == % (\photoscale = ) print photoscale == % (\ninurllink = ) print inurllink == % (\ninfilemane = ) print infilename == translate % adjust position for final figure ??? inurllink setareaurl % autolink sizing /DeviceRGB setcolorspace % pick color model 0 0 translate % set page position hpixels vpixels scale % magnify unit square photoscale dup scale /infile infilename (r) file def % establish input read file /Data {infile /DCTDecode filter} def % define a data source << % start image dicationary /ImageType 1 % always one /Width hpixels % JPEG width in pixels /Height vpixels % JPEG height in pixels /ImageMatrix [hpixels 0 0 vpixels neg 0 vpixels ] /DataSource Data % proc to get filtered JPEG /BitsPerComponent 8 % color resolution /Decode [0 1 0 1 0 1] % per red book 4.10 >> image % call the image operator ypos snap2 restore /ypos exch def } def /setareaurl { % for auto include routine /cururlname exch store mark % start pdfmark /Rect [ 0 0 hpixels photoscale mul vpixels photoscale mul ] /Border [ 0 0 0] % [0 0 0 ] = none; [0 0 2] = debug /Color [ .7 0 0 ] /Action <> /Subtype /Link /ANN % annotation type pdfmark % call pdf operators } def /settextblock {save /ssnap exch store /msg exch store /yinc exch store /txtwide exch store msg cf ssnap restore} store /burpleheader {save /ssnap exch store /msg exch store translate 0 0 mt 2 pu txtwide pr 2 pd closepath gsave 0.7 setlinewidth 154 setwebtint stroke grestore 202 setwebtint fill font7 black 1 0.6 msg cl ssnap restore } store /orangebox {save /ssnap exch store /just exch store /msg exch store /ohigh exch store /owide exch store /ypos exch store /xpos exch store xpos ypos translate 0 0 mt ohigh pu owide pr ohigh pd closepath gsave 29 setwebtint fill grestore gsave 2 setwebtint 0.25 setlinewidth stroke grestore font6 owide 2 div ohigh 1.5 sub msg just cvx exec ssnap restore} store /greenbox {save /ssnap exch store /just exch store /msg exch store /ohigh exch store /owide exch store /ypos exch store /xpos exch store xpos ypos translate 0 0 mt ohigh pu owide pr ohigh pd closepath gsave 33 setwebtint fill grestore gsave 12 setwebtint 0.25 setlinewidth stroke grestore font6 owide 2 div ohigh 1.5 sub msg just cvx exec ssnap restore} store /bluetitbox { save /ssnap exch store /just exch store /msg exch store /tit exch store /tithi exch store /tothi exch store /wide exch store translate 0 0 mt tothi pu wide pr tothi pd closepath gsave 213 setwebtint fill grestore 192 setwebtint 0.2 setlinewidth stroke 0 tothi mt wide pr tithi pd wide pl closepath 192 setwebtint fill font3 wide 2 div tothi 1.3 sub tit white cc font1 1.5 tothi 4 sub black msg just cvx exec ssnap restore} store /greentitbox { save /ssnap exch store /just exch store /msg exch store /tit exch store /tithi exch store /tothi exch store /wide exch store translate 0 0 mt tothi pu wide pr tothi pd closepath gsave 33 setwebtint fill grestore 12 setwebtint 0.2 setlinewidth stroke 0 tothi mt wide pr tithi pd wide pl closepath 12 setwebtint fill font3 wide 2 div tothi 1.3 sub tit white cc font1 1.5 tothi 4 sub black msg just cvx exec ssnap restore} store %%% tractor %%%% % xpos ypos numbholes (code) {proc} tractpr /tractor { save /ssnap exch store /tproc exch store /tcode exch store /numholes exch store translate /thigh numholes 5 mul store /twide 51 store 0 0 mt thigh pu twide pr thigh pd closepath gsave 172 setwebtint fill grestore 0.1 setlinewidth black stroke [ 1 0.65 ] 0 setdash 3 0 mt thigh pu stroke twide 3 sub 0 mt thigh pu stroke [ ] 0 setdash /hole { gsave translate newpath 0 0 0.5 0 360 arc gsave white fill grestore 0.1 setlinewidth black stroke grestore } store gsave 1.5 0 translate numholes {0 2.5 hole 0 5 translate} repeat grestore gsave twide 1.5 sub 0 translate numholes {0 2.5 hole 0 5 translate} repeat grestore save /ssnap exch store tproc ssnap restore save /ssnap exch store font9 0 0 tcode cl ssnap restore ssnap restore} store % fattail [ tipx tipy tailx taily tipfat tailfat tipdepth tipspread ] fattailne /fattailne { gsave aload pop /tipspread exch store /tipdepth exch store /tailfat exch store /tipfat exch store /taily exch store /tailx exch store /tipy exch store /tipx exch store /enthu 0.28 store /deltaxn tipx tipdepth sub tailx tailfat 2 div add sub enthu mul store /deltaxs tipx tipdepth sub tailx tailfat 2 div sub sub enthu mul store /deltaye taily tipy tipfat 2 div sub sub enthu mul store /deltayw taily tipy tipfat 2 div add sub enthu mul store tipx tipy mt tipx tipdepth sub tipy tipspread 2 div add lineto tipspread 2 div tipfat 2 div sub pd tipx tipdepth sub deltaxn sub tipy tipfat 2 div add tailx tailfat 2 div add taily deltayw sub tailx tailfat 2 div add taily curveto tailfat pl tailx tailfat 2 div sub taily deltaye sub tipx tipdepth sub deltaxs sub tipy tipfat 2 div sub tipx tipdepth sub tipy tipfat 2 div sub curveto tipspread tipfat sub 2 div pd closepath fill grestore } store /fattailnw { gsave aload pop /tipspread exch store /tipdepth exch store /tailfat exch store /tipfat exch store /taily exch store /tailx exch store /tipy exch store /tipx exch store /enthu 0.28 store /deltaxn tailx tailfat 2 div sub tipx tipdepth add sub enthu mul store /deltaxs tailx tailfat 2 div add tipx tipdepth add sub enthu mul store /deltaye taily tipy tipfat 2 div sub sub enthu mul store /deltayw taily tipy tipfat 2 div add sub enthu mul store tipx tipy mt tipx tipdepth add tipy tipspread 2 div add lineto tipspread 2 div tipfat 2 div sub pd tipx tipdepth add deltaxn add tipy tipfat 2 div add tailx tailfat 2 div sub taily deltayw sub tailx tailfat 2 div sub taily curveto tailfat pr tailx tailfat 2 div add taily deltaye sub tipx tipdepth add deltaxs add tipy tipfat 2 div sub tipx tipdepth add tipy tipfat 2 div sub curveto tipspread tipfat sub 2 div pd closepath fill grestore } store % sequence is [ tipx tipy tailx taily tipfat tailfat tipdepth tipspread ] /fattailwe { gsave aload pop /tipspread exch store /tipdepth exch store /tailfat exch store /tipfat exch store /taily exch store /tailx exch store /tipy exch store /tipx exch store /enthu 0.28 store /deltax tipx tipdepth add tailx sub enthu mul store tipx tipy mt tipx tipdepth sub tipy tipspread 2 div add lineto tipspread 2 div tipfat 2 div sub pd tipx tipdepth sub deltax sub tipy tipfat 2 div add tailx deltax add taily tailfat 2 div add tailx taily tailfat 2 div add curveto tailfat pd tailx deltax add taily tailfat 2 div sub tipx tipdepth sub deltax sub tipy tipfat 2 div sub tipx tipdepth sub tipy tipfat 2 div sub curveto tipspread tipfat sub 2 div pd closepath fill grestore } store %%%%%%% east tail, west tip %%%%%%% /fattailew { gsave aload pop /tipspread exch store /tipdepth exch store /tailfat exch store /tipfat exch store /taily exch store /tailx exch store /tipy exch store /tipx exch store /enthu 0.28 store /deltax tailx tipx tipdepth add sub enthu mul store tipx tipy mt tipx tipdepth add tipy tipspread 2 div add lineto tipspread 2 div tipfat 2 div sub pd tipx tipdepth add deltax add tipy tipfat 2 div add % debug tailx deltax sub taily tailfat 2 div add % debug tailx taily tailfat 2 div add curveto tailfat pd tailx deltax sub taily tailfat 2 div sub % debug tipx tipdepth add deltax add tipy tipfat 2 div sub % debug tipx tipdepth add tipy tipfat 2 div sub curveto tipspread tipfat sub 2 div pd closepath fill grestore } store %%%%%%% south tail, west tip %%%%%%% /fattailsw { gsave aload pop /tipspread exch store /tipdepth exch store /tailfat exch store /tipfat exch store /taily exch store /tailx exch store /tipy exch store /tipx exch store /enthu 0.28 store /deltaxn tailx tailfat 2 div add tipx tipdepth add sub enthu mul store /deltaxs tailx tailfat 2 div sub tipx tipdepth add sub enthu mul store /deltaye tipy tipfat 2 div add taily sub enthu mul store /deltayw tipy tipfat 2 div sub taily sub enthu mul store tipx tipy mt tipx tipdepth add tipy tipspread 2 div add lineto tipspread 2 div tipfat 2 div sub pd tipx tipdepth add deltaxn add tipy tipfat 2 div add % debug tailx tailfat 2 div add taily deltaye add % debug tailx tailfat 2 div add taily curveto tailfat pl tailx tailfat 2 div sub taily deltayw add % debug tipx tipdepth add deltaxs add tipy tipfat 2 div sub % debug tipx tipdepth add tipy tipfat 2 div sub curveto tipspread tipfat sub 2 div pd closepath fill grestore } store %%%%%%%%%%% Cover and page 29 %%%%%%%%%%%%%%%%% false setuppage % true = showgrid /imagelocaldirectory (C:/Users/don/Desktop/Tearing/) store % sin fwd slashes for win /imageremotedirectory (http://www.tinaja.com/images/) store % sin fwd slashes for chrome /imageurl imageremotedirectory (/apple3.jpg) mergestr store % goto remote image /imagelocalsource imagelocaldirectory (/apple3.jpg) mergestr store % comes from local file 39 50 % page translate ( data for jpegimageprocwithlink ) 878 1198 % hpixels and vpixels 0.1 0.11 mul % photoscale imagelocalsource % local jpg source imageurl % image url on clickthru jpegimageprocwithlink /adj {/txtwide 14 store -7 0 translate} store /textx (|/adj |y |6This method of breaking down and understanding someone else's Apple machine language code is \261 to say the least \261 very unique. Here are full details on how to rapidly crack both the form and the function of any tough program. It takes only one-tenth of the time of more orthodox methods.) store 25 20.5 17 13.5 textx /cf greenbox 16 41 (|0|/makeblue TEARING INTO) cl 16 39 (|0|/makeblue MACHINE LANGUAGE CODE) cl 16 53.5 (|-|/makeblue Enhancement) cl 0 62 17 6 (This |jenhancement|j|jworks |jon |jall Apples and knockoffs. |kThere are additional |jfeatures |javailable |jin the Apple IIe.) /cc orangebox /text1 (|3|/makeblue TEARING INTO MACHINE LANGUAGE CODE |h|p |/makeblack |1Check into the top thirty Apple programs used today and guess what? At this writing, thirty out of thirty will run wholly, or at least partly, in machine language! |h So, while BASIC language people are busy foisting computer literacy off onto the unwashed masses, and while Pascal people are stuffily trying to salvage what scant few shards remain of the once mighty computer science theocracy, and while FORTH people are out acting like spoiled brats\274 while all of this is happening\274 |h Machine language programmers are laughing to themselves all the way to the bank!) store 16 16 text1 cf showpage %%%%%%%%%%% page 30 %%%%%%%%%%%%%%%%% false setuppage 30 evenheader /text1 (|0|/makeblue T|1|/makeblack |k|k|khe evidence is in and it is overwhelming. Cash on the line. If you want to write a classic program or a best selling program, it |/makeblue |3must |1|/makeblack execute either wholly, or in part, in machine language. |h|p Why? |h Because machine language is far and away the fastest running, the most compact, the most flexible, the most versatile, and the one and only language that most fully utilizes all of the Apple's resources. |h The only sure way to learn machine language programming is to do lots of it on your own. But one thing that can help you a lot is to tear apart the winning machine language programs of others to see what makes them tick. |h You might also like to modify someone else's machine language program to suit your own needs. Maybe you would like to locate the scroll hooks in the HRCG High-Resolution Character Generator. Or perhaps you want to modify the original |/makeblue Apple Writer|/makeblack to output imbedded print format commands to your daisywheel. Or change FID to add your own "undelete file" command. Or maybe you have to modify a printer driver to handle HIRES graphics dumps. Or you might need some stunning animation. Or want to know what makes an adventure tick. Or whatever. |h At any rate, if you brute-force attack someone else's machine language program and if the program is more than a few hundred bytes long, chances are it will take you a very long time to crack it to the point where you think you understand it. |h I'd like to share with you a method I use that will crack any unknown machine language program astonishingly fast. The method does odd things odd ways, but ends up taking one tenth the time and one tenth the effort of any usual approach. |h We'll assume you already know and have done some machine language programming, and that the target program you want to tear into was written by an experienced and more or less rational programmer who didn't go very far out of his way to make things rough for you. Let's see what is involved. |z |/makeblue |3THE TOOLS |h|p |/makeblack |1First, we'll have to put together a toolkit. You should have a tractor-feed printer along with some heavy white paper, preferably 20-pound. Naturally, you will also need a plastic 6502 Programming Card and, of course, the 6502 Programming Manual. The following listing gives a breakdown of the tools you will need to effectively tear apart machine language programs. |h You will also want all the usual Apple manuals, along with a copy of the Apple Monitor Peeled, and, if you can find one, a copy of the old red Apple Book. I am also laboring under the delusion that you will find Don Lancaster's Micro Cookbook, Volumes 1 and 2, of help (|jSAMS #21828 and #21829|j). Try to get an Apple that has access to both an autostart ROM on a switchable plug-in card, and the old monitor ROM, without autostart, in socket F8 on the mainframe. |h This original ROM has the Trace feature, which was removed to make way for the autostart function. More importantly, the "old" ROM gives you the absolute control that is needed to stop any program at any time for any reason. Ads in |/makeblue Computer Shopper|/makeblue offer this ROM for $10.00. |h Note that many newer programs will not let you drop into the monitor when you use the autostart ROM. Instead, they adjust the pointers so that they return to themselves on a system reset. Thus, an old ROM may be absolutely essential to view the target code. The Apple lle may need custom EPROMs.) store 0 69 text1 cf showpage %%%%%%%%%%% page 31 %%%%%%%%%%%%%%%%% false setuppage 31 oddheader /adj {0 -0.3 translate} store /makedkblue { 192 setwebtint} store 14 30 % xpos ypos 17 40 % wide high 3 % title high (MACHINE LANGUAGE TOOLKIT) ( ( ) 48K Apple II, preferably with an old ROM in mainframe and a switchable autostart. ROM on plug-in card. |/adj ( ) Tractor-feed printer. |/adj ( ) Heavy white tractor paper. |/adj ( ) 6502 Programming Card. |/adj ( ) 6502 Programming Manual. |/adj ( ) All Apple manuals. |/adj ( ) Apple monitor peeled book |/adj ( ) Apple red book. |/adj ( ) Apple Monitor Peeled book. |/adj ( ) Lancaster's Micro Cookbook, Volumes 1 and 2. |/adj ( ) Roll of transparent tape. |/adj ( ) Case of page highlighters, in all available colors. |/adj ( ) Fine and regular felt-tip pens of matching colors. |/adj ( ) Serendipity scratch pad. |/adj ( ) What if? quadrille pad. |/adj ( ) |/makedkblue |3PAGE HIGHLIGHTERS |/adj |/makeblack |1|/black ( ) A quiet workspace. |/adj ( ) The right attitude. ) (cl) bluetitbox /adj {0 -0.9 translate} store 34 30 % xpos ypos 17 40 % wide high 3 % title high (TOOLKIT\nReSOURCES) ( ( ) 6502 PROG MANUAL Rockwell International Box 3669 Anaheim, CA 92803 Tel: 714-632-0950 |/adj ( ) 6502 PLASTIC CARD Micro Logic Corp. Box 174 Hackensack, NJ 07602 Tel: 201-342-6518 |/adj ( ) APPLE MONITOR PEELED 14349 San Jose Street Mission Hills, CA 91345 Tel: 213-896-6553 |/adj ( ) THE MICRO COOKBOOKS Howard W. Sams & Co., Inc. 4300 West 62nd Street Indianapolis, IN 46268 Tel: 317-298-5566 |/adj ( ) PAGE HIGHLIGHTERS #2500A Major Accent Sanford Corp. Bellwood, IL 60104 Tel: 312-547-3272 (SEARS #3KX-3272) ) (cl) bluetitbox /text1 (|p|y |1If you really get into machine language programming, this original firmware ROM is very, very useful. I suspect these ROMs may eventually become rare, but with 2716 EPROMs now under $5.00, you can easily clone your own by adding a simple CS adaptor to ROM socket F8. |h You will want at least a 48K machine, and if there is extra RAM on plug-in ards, so much the better. The big advantage to having more RAM than the program needs is that you are free to add your own test and debug programs co-resident with whatever target program you are tearing apart. You should have oth a cassette and at least one disk drive. The cassette can always save any mage of any part of any program at any time, regardless of whether there is a DOS operating system there or not. Images on the tape can be split up and relocated as needed, letting you transfer them to disk at your convenience. The cassette can also let you introduce very small "test" and "hook" programs into he darndest spaces. |h Now, off to the office supply. Get yourself a big roll of transparent mending tape \261 the kind you can write on. Then get two cases \261 yes, cases \216 of page highlighters. Throw away all the extra yellow ones, and get as many different colors as you can. Match each page highlighter with both a fine point and a regular felt-tip pen of the same color.) store 16 28 text1 cf showpage %%%%%%%%%%%%%%%% page 32- %%%%%%%%%%%%% false setuppage 32 oddheader /proc2 {gsave translate 5715 srand /procwide 16 store 0 4 mt 14 pu procwide { 0.5 3 random 1 sub 0.3 mul rlineto} repeat 18 pd 5715 srand procwide { -0.5 3 random 1 sub 0.3 mul rlineto} repeat 7 pu closepath gsave 141 setwebtint fill grestore 24 setwebtint 0.2 setlinewidth stroke /subproc { 0 2.5 mt 4 pu procwide 2 div pr 4 pd closepath gsave white fill grestore 24 setwebtint stroke black procwide 4 div 4.3 (|3 CODE\nMODULE) cc 0 6 mt 2 pu procwide 2 div pr 2 pd closepath gsave white fill grestore 24 setwebtint stroke black procwide 4 div 6.6 (|3 STASH) cc } store subproc 0 7.5 translate subproc grestore } store /proc1 {gsave translate 0 5 mt 16 pu 8 pr 16 pd closepath 141 setwebtint fill 0 0 mt 21 pu 8 pr 21 pd closepath 24 setwebtint 0.2 setlinewidth stroke 0 5 mt 8 r black 4 2.3 (|3 ACTION) cc 4 13.5 (|3BULK\nFILES) cc -1 -0.3 (|1START) cr -1 20.3 (|1END) cr grestore } store 6 21 proc1 22 22 proc2 /fattailwe { gsave aload pop /tipspread exch store /tipdepth exch store /tailfat exch store /tipfat exch store /taily exch store /tailx exch store /tipy exch store /tipx exch store /enthu 0.28 store /deltax tipx tipdepth add tailx sub enthu mul store tipx tipy mt tipx tipdepth sub tipy tipspread 2 div add lineto tipspread 2 div tipfat 2 div sub pd tipx tipdepth sub deltax sub tipy tipfat 2 div add tailx deltax add taily tailfat 2 div add tailx taily tailfat 2 div add curveto tailfat pd tailx deltax add taily tailfat 2 div sub tipx tipdepth sub deltax sub tipy tipfat 2 div sub tipx tipdepth sub tipy tipfat 2 div sub curveto tipspread tipfat sub 2 div pd closepath fill grestore } store % [ tipx tipy tailx taily tipfat tailfat tipdepth tipspread ] fattailne 198 setwebtint [21.5 31 14.5 24 1 3 2 2 ] fattailwe black 6 19 (|3Fig. 3-1. A "typical" machine language program.) cl % sequence is [ tipx tipy tailx taily tipfat tailfat tipdepth tipspread ] /text1 (|p|1|p|y Don't underestimate the importance of these page highlighters. This method starts out real stupid like, but you will be astounded when the truth and beauty of what is happening leaps out at you halfway through. |/makeblue The |/makeblue highlighters are absolutely essential! |/makeblack Make sure these are the fat "see through" kind. Get yourself some scratch pads as well. Label the little blank one "Serendipity" and the bit quadrille one "What if?". |h You also have to have the right attitude, the right workspace, patience, persistence, curiosity, perversity, and a very distorted sense of humor for this method to work. |h It is extremely important that you do everything that follows hands on and by yourself. |/makered |3Do not, under any circumstances, let someone else or the |/makered Apple help you with any tedious or dogwork parts.|1 |/makeblack The method relies heavily on your subconscious putting together the big picture and sewing up the loose ends. It can only do this if it has access to everything that the tearing attack method needs. Do the dull stuff yourself! |z |/makeblue |3THE FIRST RULE |h |/makeblack |1What can we expect to find inside a machine language program? The working code for sure. But, besides that working code, we need files that go with that code. In most longer machine language programs, the files often take up far more room than the working code does.) store /text2 (|p|y |1Fig. 3-1 shows your "typical" machine language program, which is just about as representative as your " typical" Apple owner or your "typical" rock. We see that there are usually two main areas to any larger machine language program. These are the |/makeblue |3action|/makeblack |1 and the |/makeblue |3bulk files. |h |1 The action is the "real" part of the program that actually does things. The action, in turn, is made up of two different types of blocks. These blocks are called code |/makeblue |3modules|1|/makeblack and |/makeblue |3stashes|/makeblack |1 . |h|p A code module is a chunk of working machine language code that does something. In most programs, most of the modules are subroutines, and are called as needed from a very short main program. The advantages of subroutines are that they break things down into small and understandable chunks and that they can be accessed from several places in the main program at once.) store 0 69.5 text1 cf 0 17 text2 cf showpage %%%%%%%%%%%%%%%% page 33 %%%%%%%%%%%%% false setuppage 33 oddheader /imagelocaldirectory (C:/Users/don/Desktop/Tearing/) store % sin fwd slashes for win /imageremotedirectory (http://www.tinaja.com/images/) store % sin fwd slashes for chrome /imageurl imageremotedirectory (/key1.jpg) mergestr store % goto remote image /imagelocalsource imagelocaldirectory (/key1.jpg) mergestr store % comes from local file 17.7 35.2 % page translate ( data for jpegimageprocwithlink ) 450 232 % hpixels and vpixels 0.1 0.26 mul % photoscale imagelocalsource % local jpg source imageurl % image url on clickthru jpegimageprocwithlink 25.3 39.3 (|/makeblue |0THE) cc % goes with key 32 35.5 17 5 (Find out the STRUCTURE and the FLOW of any program, and most of |kthe |kcode |k|kwill |ktake |kcare |kof |kitself!) /cc orangebox /text1 (|p|y |1A stash is a short file that works directly with a module. The stash often follows immediately after the module that uses it. Typical stash entries might be a short ASCII string, a list of condition codes, or a table of indirect addresses. The stash holds values needed by the module that it works with. |h The bulk files are usually much longer than the stashes. Bulk files normally sit off by themselves and usually follow the action. An example of a bulk file might be a high resolution character set. The action controls how and when the character codes in the bulk file character set go on the screen. In a medium sized adventure, the bulk files may contain the map, the script, the objects, the responses, the rooms, and anything else unique to one particular story line. Only the bulk file has to be changed to change the adventure. The action can often stay the same. |h In animated games or other programs that use the HIRES features, the bulk file may actually be the HIRES screen pages, or combinations of these pages with extra file space. |h If you are into very fancy machine language programs, the action may, in fact, be an interpreter acting as a special use language. The bulk files will then contain commands that are run under the action's command interpretation. Zork is a classic example of this type of thing. In Zork, the action is a LISP-like interpreter specially written in compact and fast machine language code. |h The absolute key secret to tearing into machine language code is ...) store /text2 (|p|y |1So, never, never, never start taking apart machine language code on a line by line basis. This is a total waste of time and will take forever. Not to mention that it won't work anyhow. The whole trick is to find out the structure of the program. Separate each module of the program and then separate each file from everything else. |h You'll find out there are very powerful hidden indicators that will leap out at you when you look for them. These indicators will very rapidly break everything down into simple, obvious, easy-to-understand, and self documenting chunks. |h Don't believe me? Let's try it and see. We'll use Apple's own HRCG High Resolution Character Generator as a target program to show you how the method works and to illustrate key points. We'll go over the method in some detail. Later, we'll sum everything up in one checklist. HRCG is available on the DOS 3.3 TOOLKIT diskette, available from most dealers. You'll get the most out of what follows by actually doing each and every step using your own copy of HRCG as we go along. Then try the method on a target program of your own choosing. |z |/makeblue |6THE METHOD |h|p |1Ready? Here we go\274) store /text3 (|p|y |1You must be thoroughly familiar with what the program does and how it works before you start. Never try to crack a code until after you have used the program and really and truly know it.) store 16 6 (GROK THE PROGRAM) burpleheader 16 69 text1 cf 16 33 text2 cf 16 4 text3 cf showpage %%%%%%%%%%%%%%%% page 34 %%%%%%%%%%%%% false setuppage 34 evenheader /text1 (|p|y |1For instance, there's absolutely no point in taking apart |/makeblue |1Pyramid of Doom|1|/makeblack to try and find the shovel. If you can't find the shovel, you just aren't cut out for Adventure. But, you just might want to tear into it to find the last treasure you need to replace the treasure you have to destroy to get past a certain \261 uh \261 inconvenience halfway up the pyramid. In no way will your first tearing into Adventure tell you the last treasure is in the dressing room, but you'll learn a lot about machine language and machine language programs as you go along. |h In the case of the HRCG, use the program and thoroughly explore all the alternate character fonts, and all the options of each and every mode of operation. Know exactly what the program does before you try to tear into it. |h One limit to this, though\274) store /text2 (|p|y |1Thus, while you are learning how to use the program, and while you may think you have some good ideas on how the program works, reserve judgement till later. All your good ideas will invariably turn out to be 100% wrong. |h If you can, watch others use the program and look into their reactions of how the program works and what it does. You may be missing something totally obvious. Rap with others as much as possible.) store /text3 (|p|y |1Read every scrap of documentation that comes with the program, no matter how badly written or misdirected it may seem. Always ask around to see if the source code exists somewhere. Be sure to look into updates and revisions as well. |h It is infinitely easier to start with the original author's source code and work into the program, than to start with an unknown bunch of code and try to infer what the author had in mind in the first place. |h If there is no documentation or if it isn't helpful, and if the original source code isn't available, keep checking. Perhaps others have torn into part of the code or have made modifications on their own that seem to work. Ask around at your club, school, computer store, bulletin board, or user group. If anything is available that seems to help, try it. |h Anything else that can give you a clue to where the software author's head is and where he is coming from will be of great help. Maybe he publishes articles and stories. Maybe he has a series of programs out that can be of use. A few moments of asking in the right places can save you months of time. |h So, always check around.) store /text4 (|p|y |1Any genuinely experienced programmer will admit to this rule\274) store 9 49.7 17 5 (NEVER assume a program works in a certain manner or "has" to do something in an obvious way!) /cc orangebox 0 36.8 (GO TO THE HORSE'S WHATEVER) burpleheader 0 10 (HAVE A LIMITED GOAL) burpleheader 0 69 text1 cf 0 48 text2 cf 0 34.8 text3 cf 0 8 text4 cf 9.2 1.3 17 5 (A long program is NEVER fully debugged |knor |kfully |kunderstood. Nor can it ever be.) /cc orangebox 31 4 (|/makeblue |-BELIEVE\n|h\n|/makeblue IT!) cc 8.5 1.3 (|;|/makeblue +) cr % zapf? showpage %%%%%%%%%%%%%%%% page 35 %%%%%%%%%%%%% false setuppage 35 oddheader /text1 (|p|y |1The entire DEW (Distant Early Warning) defense radar program was never tested. Not only was it never tested, the DEW program was so hopelessly complex that there was no possible way it could have been fully tested. Even if some test method existed, the odds of it passing any test was infinitely small. |h A good and clean program simply has most of its remaining bugs fairly well hidden and fairly well out of the mainstream. This only happens after the ninth or tenth revision. But rest assured, there are definitely still bugs there, lying in "deep cover" and patiently waiting. |h What this says is that the original programmer did not fully understand nor fully debug his program. If he says he has, he is either lying or else hopelessly naive. Now, if he didn't understand his own program, why should you? |h Thus, a goal "to completely understand" some program is not only unreasonable; it is patently ridiculous. Instead, set yourself a reasonable and realistic goal for your first trip of tearing into machine code. Then, after you have set this realistic goal, simplify it till it is trivial. Then, simplify that. Then, think up some really dumb test of a small part of what is left. Something any idiot could hack. Maybe, just maybe, you will then be in the ball park. |h For the HRCG, let's use the goal of answering "Where are the scroll hooks?" The HRCG obviously has some sort of scroll in it, since it moves characters up the screen. The scroll on the version I received is abrupt and chunky, so it can obviously be improved. Or can it? |h Maybe it's not so obvious. Why would such a good program have such an ugly scroll? These are name-brand people working on this and chances are they fumed and fretted over things quite a bit. Better stick with our original goal of finding the scroll hooks. |h When you set your limited goal, don't become obsessed with it. The tearing method works by separating the known from the unknown as you go through the code. The method we will use demands a lot of apparently useless side trips. Concentrate only on your goal and you may never get there.) store /text2 (|p|y |1Before we can go on with our tearing attack method, we have to take time out for a rather long, but most essential side trip. Ready? Here we go\274 |h Where is the machine language program likely to sit? A glib answer is some- where between $0000 and $FFFF, unless they are using memory mapping to go beyond 64K or are swapping things back and forth to the disk, or are using auxiliary memory on the Apple IIe. This assumes, of course. that the program is not self-modifying so that it changes itself through time. |h Figs. 3-2 through 3-6 show us some places we can put a program. We can divide these into low RAM, high RAM and wherever. Let's check these in more detail. |z |6|/makeblue Low RAM |h|/makeblack |p |1Low RAM is heavily used. As Fig. 3-2 shows us, low RAM goes from hex $0000 through $07FF, or memory pages Zero through Seven. |h Page Zero is very valuable real estate for two reasons. The first is the 6502 has a page Zero addressing mode that is much shorter and faster than most |k) store 16 28.3 (FIND WHERE THE PROGRAM SITS) burpleheader 16 69 text1 cf 16 26 text2 cf showpage %%%%%%%%%%%%%%%% page 36- %%%%%%%%%%%%% false setuppage 36 evenheader 25 66 (|3Fig. 3-2. Low RAM memory map.) cl /text11(|z|y |4PAGES FOUR THROUGH SEVEN ARE THE TEXT AND LORES PAGE ONE. THERE ARE ALSO 64 LOCATIONS IN 8 GROUPS OF 8 EACH INTENDED FOR I/O USE. ) store /text22(|z|y |4PAGE THREE HOLDS THE DOS POINTERS AND MONITOR VECTORS AT ITS HIGH END. THE BOTTOM OF THIS PAGE IS A POPULAR PLACE TO PUT PROTECTED MACHINE LANGUAGE CODE. ) store /text33 (|z|y |4PAGE TWO IS THE KEYBOARD INPUT BUFFER AND WORKS FROM THE BOTTOM UP. SHORT PROGRAMS CAN BE PUT AT THE TOP OF THIS PAGE, BUT A DANGER EXISTS OF A LONG KEYBOARD ENTRY PLOWING THE PROGRAM. ) store /text44(|z|y |4PAGE ONE IS THE STACK AND WORKS FROM THE TOP DOWN. SHORT PROGRAMS CAN BE PUT AT THE BOTTOM OF THIS PAGE, BUT A DUAL DANGER EXISTS OF YOUR PROGRAM PLOWING THE STACK, AND VICE VERSA. ) store /text55(|z|y |4PAGE ZERO HOLDS CALCULATED ADDRESSES. ALL VALUES PASSED BETWEEN PROGRAMS, AND MOST SYSTEM VARIABLES. THERE IS USUALLY NO ROOM FOR ACTUAL PROGRAM CODE, ALTHOUGH MOST PROGRAMS DO USE THESE LOCATIONS FOR STORAGE. ) store save /txtwide 27 store 22 61.5 text11 cf restore save /txtwide 27 store 22 56.5 text22 cf restore save /txtwide 27 store 22 51.5 text33 cf restore save /txtwide 27 store 22 45.5 text44 cf restore save /txtwide 27 store 22 39.5 text55 cf restore % fattail [ tipx tipy tailx taily tipfat tailfat tipdepth tipspread ] fattailew 198 setwebtint [ 14.5 36.5 21.5 38 1 3 2 2 ] fattailew [ 14.5 41.5 21.5 44 1 3 2 2 ] fattailew [ 14.5 46.5 21.5 50 1 3 2 2 ] fattailew [ 14.5 51.5 21.5 55.5 1 3 2 2 ] fattailew [ 14.5 58.5 21.5 60.5 1 3 2 2 ] fattailew black /proc2 {gsave translate 5715 srand /procwide 16 store 0 4 mt 31 pu procwide { 0.5 3 random 1 sub 0.3 mul rlineto} repeat 35.5 pd % 5715 srand procwide { -0.5 3 random 1 sub 0.3 mul rlineto} repeat 8 pl 7 pu closepath gsave 141 setwebtint fill grestore 24 setwebtint 0.2 setlinewidth stroke 24 setwebtint 0 1 mt 8 pu 0.2 setlinewidth stroke 24 setwebtint 0 1 mt 8 pu 0.2 setlinewidth stroke 0 0 mt 5 pu 8 pr 5 pd closepath gsave white fill grestore 24 setwebtint 0.2 setlinewidth stroke 0 5 mt 5 pu 8 pr 5 pd closepath gsave white fill grestore 24 setwebtint 0.2 setlinewidth stroke 0 10 mt 5 pu 8 pr 5 pd closepath gsave white fill grestore 24 setwebtint 0.2 setlinewidth stroke 0 15 mt 5 pu 8 pr 5 pd closepath gsave white fill grestore 24 setwebtint 0.2 setlinewidth stroke 0 20 mt 13 pu 8 pr 13 pd closepath gsave white fill grestore 24 setwebtint 0.2 setlinewidth stroke 24 setwebtint 0 30 mt 30 pd 8 pr 30 pu stroke black 4 3.3 (|3POINTERS\nAND\nVECTORS) cc 4 7.2(|3STACK ) cc 4 12.5 (|3KEY-IN\nBUFFER)cc 4 17.5 (|3SYSTEM\nVECTORS) cc 4 27.2 (|3TEXT AND\nLORES\nPAGE 1) cc -1 -0.4 (|1$0000) cr -1 4.5 (|1$0100) cr -1 9.5 (|1$0200) cr -1 14.8(|1$0300) cr -1 19.8 (|1$0400) cr -1 31.8 (|1$07FF) cr grestore } store 6 34 proc2 5.2 9.5 23 8 (Practically all programs need a few locations on page Zero. Some of these are used to pass values to the monitor, to|k BASIC, |kor |kelsewhere. |k |h Other page Zero locations can be used to hold calculated addresses for the indirect modes. |k) /cc orangebox /text1 (|z|y |1indirect indexed and indexed indirect demand pairs of address locations on page Zero. |h|p The Apple book shows how practically all of page Zero is used up one way or another by the monitor, the DOS, or either BASIC. For instance, the locations for the keyboard entry hooks and the print output hooks are stored as addresses on page Zero, as are the screen formatting controls that set the height and width of the display. Other important page Zero locations convert line numbers into the base addresses needed to hit a certain line of video. |h|p We will see a list of these important page Zero locations shortly. The point here is \274) store /text2 (|pThus, page Zero real estate is far too costly for program code. Instead, the available locations are used to pass values back and forth between the system and the target program, and to hold calculated address values. |h Sometimes a target program will reassign page Zero locations for its own use. For instance, if the program is fully in machine language, it could borrow |k) store /text2 (|p|y |1Thus, page Zero real estate is far too costly for program code. Instead, the available locations are used to pass values back and forth between the system and the target program, and to hold calculated address values. |h Sometimes a target program will reassign page Zero locations for its own use. For instance, if the program is fully in machine language, it could borrow |k) store 0 31 text1 cf 0 7.5 text2 cf showpage %%%%%%%%%%%%%%%% page 37 %%%%%%%%%%%%% false setuppage 37 oddheader /text1 (|z|y |1many of the locations "reserved" for Applesoft or Integer BASIC, since these locations will never be used. Monitor locations that serve oddball purposes can also be "redefined" provided that the monitor feature is never used. |h|p Occasionally a very short machine language sequence can be crammed into low values on page Zero, as was done with the original tone subroutine in the old red book. Even this got you in trouble when you switched to Applesoft. Putting programs on page Zero is dangerous and dumb, but it can be done. |h Another dangerous place to put programs is on page One. Page One is intended to be used for the stack. The 6502 uses a single stack that starts at location $01FF and builds down. This stack is shared by the monitor, by the operating system, and the program itself. Important uses of the stack are to store the return address of a subroutine call and both return address and processor status on an interrupt. Advanced programmers might also use the stack as a temporary stash of a value or two, or might even manipulate the stack to alter the program flow. |h The stack rarely gets below $0180 in normal use. It is usually possible to put a very short machine language program in locations $0100 through $017F. This is dangerous, since the program can plow the stack and vice versa, if either gets too long. |h Page Two is normally used as a keyboard buffer. Key entries start at $0200 and build their way up. The average number of keystrokes stored is fairly low, and you can sometimes cram a small machine language program on the top of this page. Once again, you are asking for trouble since too long a keyboard entry will plow your program. |h One sneaky and ugly trick that a programmer can pull is to put some relocation or protection code starting at $0200. This code must be used before any keys are hit, and is thus very difficult to read. The code will, of course, get destroyed as soon as any keys are entered. |h Most of page Three is available to the machine language programmer. There are some DOS jumps and system vectors on the high end of this page. The vectors control the reset, interrupt, autostart return, breakpoints, Applesoft "&", and nonmaskable interrupt jumps. |h Thus, you are free to use the first 150 or so locations on page Three for your machine language program. This turns out to be a favorite stash for short programs, since this area is automatically protected from either BASIC. |h Unfortunately, everybody and his brother crams just about everything they can think of in here, and you can often have two parts of a program, each of which needs a different machine language code, both trying to use this space. For instance, a printer driver may be placed here by one program and a screen dump by another. Try to combine the programs, and you have a turf fight. |h If you have a longer machine language sequence, you can sometimes combine the top half of page Two continuously with the bottom half of page Three. Again, you have to be careful not to get bumped by a long keyboard entry and to be sure you don't, in turn, bump into a DOS hook or other pointer. Memory pages Four through Seven are the page One text screen and page One LORES screen. The only difference between traditional text and LORES is that, in text, the stored code goes through a hardware character generator while, in LORES, the same code is directly bit-by-bit converted into a stacked pair of colored blocks. |h It seems kinda dumb to try and put machine language code onto the display pages. First, you will probably see it and it will look ugly. Secondly, any scrolling or screen clearing will destroy the code. Nonetheless, in a program that does all its work in HIRES, this space is theoretically available. ) store 16 69 text1 cf showpage %%%%%%%%%%%%%%%% page 38 %%%%%%%%%%%%% false setuppage 38 evenheader /text1 (|p|y |1There are some sneaky RAM locations stashed here and there on pages Four through Seven that are not displayed and are not erased by a properly done scroll or clear. There are 64 of these locations. These are normally intended for use by the I/O slots and have intended assignments. |h If you really want to be tricky, you can use these spaces any way you want to, |/makeblue |3provided there is no I/O access to the same location|/makeblack |1. This is one of the better hiding places for disk verification codes and other sneaky stuff. |h Summing our low RAM up, you have a few locations on page Zero available to you that are usable to pass values to the monitor or to save calculated addresses. The low end of the page One stack and the high end of the page Two keyboard buffer can be used for short programs or subroutines, but use of these areas can be dangerous. Most of the bottom of page Three can be used for a machine language program. This space is very popular but it can cause conflicts between programs. Finally, pages Four through Seven are the page One text and LORES display and are not normally available for program storage, except for some 64 hidden locations that are normally reserved for input and output. |3|/makeblue High RAM |h |/makeblack |1As Fig. 3-3 shows us, the high RAM runs from $0800 up through the top of installed RAM. In a 48K machine, high RAM goes from $0800 through $BFFF. This area holds the usual locations where longer programs are placed. |h How much of high RAM is available for your use? It all depends on what other features you are going to run along with your program, and what minimum size Apple you want the program to run on. |h We will assume that the target program needs a full 48K. Extra RAM is now so cheap that practically all Apples either arrive with full RAM or are soon filled. With those new 64K RAM cards, most Apples will soon have bunches of extra memory on top of what used to be "fulL" A machine with a mere 48K of RAM will soon be at poverty level. |h At any rate, if you decide to use text page Two or LORES page Two, locations $0800 through $O8FF have to be set aside and protected. Use of this text page is relatively rare. |h If you want to use HIRES page One for graphics, sprite animation, or multifont text displays, then locations $2000 through $3FFF have to be reserved. Use HIRES page Two and you will also have to reserve locations $4000 through $5FFF. These locations hold an image of what goes on the screen and, thus, are not available for both display and program use at the same time. You will sometimes use both pages at once for effective and fast animation or to double graphics resolution. |h While there are a few unused RAM locations on these HIRES pages, these locations get plowed every screen reset or color change. Thus, they are not safely usable except as a very temporary stash. |h We will note in passing that if the HIRES pages are not used, and you put code in this area, you can actually watch the code executing by switching to HIRES while the program is in action. This can be a very powerful snooping tool. Watching a program run its own code gives you a new window into what is happening. You can also watch code working on LORES page Two, but this is a much smaller area and not nearly as useful. |h If you are using standard DOS, the space from $9600 through $BFFF is normally saved for the DOS system. You can sometimes "borrow" a DOS file or two and stuff a short machine language sequence into a small portion here. ) store 0 69 text1 cf showpage %%%%%%%%%%%%%%%% page 39- %%%%%%%%%%%%% false setuppage 39 oddheader /text11(|z|y |4THE DOS 3.3 OPERATING SYSTEM SITS AT THE TOP OF HIGH RAM. SMALL SMALL WORKING PROGRAMS CAN BE STORED HERE IN UNUSED DOS FILE AREAS. THIS SPACE MAY BE FREED UP BY GOING TO A SMALL CUSTOM DOS OR BY MOVING DOS ONTO A RAM CARD. ) store /text22(|z|y |4AVAILABLE PROGRAM SPACE. ) store /text33 (|z|y |4HIRES PAGE TWO IS USED FOR ANIMATION AND GAMES WHERE ONE PAGE IS DISPLAYED WHILETHE OTHER IS MODIFIED. MUST BE PROTECTED WHEN USED. ) store /text44(|z|y |4HIRES PAGE ONE RESIDES HERE AND IS USED FOR BOTH COLOR GRAPHICS AND MULTIFONT TEXT DISPLAYS. MUST BE PROTECTED WHEN USED. ) store /text55(|z|y |4AVAILABLE PROGRAM SPACE. ) store /text66(|z|y |4LORES AND TEXT PAGE TWO. VERY RARELY USED. ) store save /txtwide 27 store 22 64.5 text11 cf restore save /txtwide 27 store 22 57 text22 cf restore save /txtwide 27 store 22 54 text33 cf restore save /txtwide 27 store 22 49.5 text44 cf restore save /txtwide 27 store 22 44.5 text55 cf restore save /txtwide 27 store 22 42.5 text66 cf restore % fattail [ tipx tipy tailx taily tipfat tailfat tipdepth tipspread ] fattailew 198 setwebtint [ 14.5 44.5 21.5 42.8 1 1 2 2 ] fattailew [ 14.5 47.7 21.5 45 1 1 2 2 ] fattailew [ 14.5 52.5 21.5 48.7 1 3 2 2 ] fattailew [ 14.5 57 21.5 53 1 3 2 2 ] fattailew [ 14.5 62.5 21.5 57.5 1 1 2 2 ] fattailew [ 14.5 67.5 21.5 62.5 1 3 2 2 ] fattailew black /proc2 {gsave translate 5715 srand /procwide 16 store 0 4 mt 26 pu 8 pr % procwide { 0.5 3 random 1 sub 0.3 mul rlineto} repeat 30 pd 5715 srand procwide { -0.5 3 random 1 sub 0.3 mul rlineto} repeat % 8 pl 7 pu closepath gsave 141 setwebtint fill grestore 24 setwebtint 0.2 setlinewidth stroke 24 setwebtint 0 1 mt 8 pu 0.2 setlinewidth stroke 24 setwebtint 0 1 mt 8 pu 0.2 setlinewidth stroke 0 2.5 mt 3 pu 8 pr 3 pd closepath gsave white fill grestore 24 setwebtint 0.2 setlinewidth stroke 0 9 mt 5 pu 8 pr 5 pd closepath gsave white fill grestore 24 setwebtint 0.2 setlinewidth stroke 0 14 mt 5 pu 8 pr 5 pd closepath gsave white fill grestore 24 setwebtint 0.2 setlinewidth stroke 0 25 mt 5 pu 8 pr 5 pd closepath gsave white fill grestore 24 setwebtint 0.2 setlinewidth stroke 24 setwebtint % 0 30 mt 30 pd 8 pr 30 pu stroke black 4 4.3 (|3LORES\nPAGE 2) cc 4 12 (|3HIRES \nPAGE 1 ) cc 4 16.5 (|3HIRES\nPAGE 2)cc 4 27.3 (|3DOS 3.3) cc -1 2.5 (|1$0800) cr -1 5.0 (|1$0C00) cr -1 9 (|1$2000) cr -1 13.8(|1$4000) cr -1 18.8 (|1$6000) cr -1 24.8(|1$9600) cr -1 29.8 (|1$BFFF) cr grestore } store 6 40.5 proc2 23 39 (|3Fig. 3-3. High RAM memory map.) cl /text1 (|p|y |1A lot of programs provide their own smaller and simplified versions of DOS. This gives a measure of copy protection and makes more room. |h Thus, a machine language program could go from $0800 to $BFFF. Subtract the range $9600 through $BFFF for DOS at the top, the range $4000-$SFFF for HIRES page Two, the range $2000-$3FFF for HIRES page One, and, if used, the range $0800 through $08FF at the bottom for text and LORES page Two. |h Many machine language programs start at $0800 and work their way upwards as needed. If they are about to crash into the HIRES pages, they skip above HIRES and continue as far as they have to. |3|/makeblue Combining Programs |h |1Things get much more complicated if machine language subroutines have to interact with Integer or Applesoft BASIC programs. Each BASIC language works differently and needs a different way to "protect" an area for its machine language routines. The protection will be needed to keep the BASIC from overwriting the machine code and vice versa. Fig. 3-4 shows us more detail. |h In Integer BASIC, HIMEM is a high-memory pointer that points to the end of the Integer program. The program starts at HIMEM and builds its way downward. Every new program line gets put in its place, automatically moving everything else down and leaving you with the end of the program listing at HIMEM. String variables start at the low-memory pointer LOMEM and build their way upwards. |h The usual way to tie a machine language program into Integer BASIC is to start the machine language sequence at $0800 and set LOMEM to at least one space above the end of the machine language code. LOMEM can be set as the |k) store 16 34.5 text1 cf showpage %%%%%%%%%%%%%%%% page 40- %%%%%%%%%%%%% false setuppage 40 evenheader /procwide 16 store /proc1 {gsave translate 5715 srand 0 3.5 mt 22 pu procwide { 0.5 3 random 1 sub 0.3 mul rlineto} repeat 25.5 pd procwide { -0.5 3 random 1 sub 0.3 mul rlineto} repeat 3.5 pu closepath gsave 141 setwebtint fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 3.5 mt 3.5 pu 8 pr 3.5 pd closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 7 mt 16 pu 8 pr 16 pd closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke black 4 2 (|3TEXT 1) cc 4 5.5 (|3MACHINE\nCODE) cc 4 15.5 (|3INTEGER\nBASIC\nPROGRAM) cc 4 24 (|3DOS) cc -1 3.2 (|1$0800) cr -1 6.5 (|1???? |k) cr -1 22.7(|1$9600) cr 13 13 (|4LOMEM SET\nTO TOP OF\nMACHINE\nCODE + 1) cc 13 19.5 (|4NORMAL\nHIMEM) cc 4 -1.5 (|3(A) Integer Basic, no HIRES) cc % sequence is [ tipx tipy tailx taily tipfat tailfat tipdepth tipspread ] 198 setwebtint [ 8.5 7 13 9 0.7 2.5 1.2 2] fattailnw [ 8.5 23 13 20.5 0.7 2.5 1.2 2] fattailsw black grestore } store /proc2 {gsave translate 5715 srand 0 3.5 mt 22 pu procwide { 0.5 3 random 1 sub 0.3 mul rlineto} repeat 25.5 pd procwide { -0.5 3 random 1 sub 0.3 mul rlineto} repeat 3.5 pu closepath gsave 141 setwebtint fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 3.5 mt 3.5 pu 8 pr 3.5 pd closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 8 mt 3.5 pu 8 pr 3.5 pd closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 11.5 mt 11.5 pu 8 pr 11.5 pd closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke black 4 2 (|3TEXT 1) cc 4 5.5 (|3MACHINE\nCODE) cc 4 10 (|3HIRES\nPAGE 1) cc 4 18 (|3INTEGER\nBASIC\nPROGRAM) cc 4 24 (|3DOS) cc -1 3.2 (|1$0800) cr -1 6.7 (|1???? |k) cr -1 7.7 (|1$2000) cr -1 11.3 (|1$4000) cr -1 22.7 (|1$9600) cr 13 8 (|4LOMEM SET\nTO $4000) cc 13 19.5 (|4NORMAL\nHIMEM) cc % sequence is [ tipx tipy tailx taily tipfat tailfat tipdepth tipspread ] 198 setwebtint [ 8.5 11.5 13 9 0.7 2.5 1.2 2] fattailsw [ 8.5 23 13 20.5 0.7 2.5 1.2 2] fattailsw black 4 -1.5 (|3(B) Integer Basic using HIRES 1) cc grestore } store /proc3 {gsave translate 5715 srand 0 3 mt 24 pu procwide { 0.5 3 random 1 sub 0.3 mul rlineto} repeat 26.5 pd procwide { -0.5 3 random 1 sub 0.3 mul rlineto} repeat 3.5 pu closepath gsave 141 setwebtint fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 3.5 mt 8 pu 8 pr 8 pd closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke % 0 10.5 mt 4 pu 8 pr 4 pd closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 11.5 mt 8 pu 8 pr 8 pd closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 19.5 mt 5 pu 8 pr 5 pd closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke black 4 2 (|3TEXT 1) cc 4 8 (|3APPLESOFT\nPROGRAM\nLINES) cc % 4 12.7 (|3HIRES\nPAGE 1) cc 4 16.3 (|3APPLESOFT\nSTRINGS AND\nVARIABLES) cc 4 22 (|3MACHINE\nCODE) cc 4 25.5 (|3DOS) cc -1 3.2 (|1$0800) cr -1 11.2 (|1???? |k) cr % -1 10.2(|1$2000) cr % -1 14.2 (|1$4000) cr -1 19.2 (|1???? |k) cr -1 24.3 (|1$9600) cr 13 10 (|4START OF\nPROGRAM\nPOINTER SET\nTO $0800) cc 13 16 (|4LOMEM) cc 13 26 (|4HIMEM SET\nTO BOTTOM\nOF MACHINE\nCODE -1) cc % sequence is [ tipx tipy tailx taily tipfat tailfat tipdepth tipspread ] 198 setwebtint [ 8.5 3.5 13 6 0.7 2.5 1.2 2] fattailnw [ 8.5 11.5 13 15.5 0.7 2.5 1.2 2] fattailnw [ 8.5 19.5 13 22 0.7 2.5 1.2 2] fattailnw black 4 -1.5 (|3(C) Applesoft Basic, no HIRES 1) cc grestore } store %%%%%%%%% %%%%% /proc4 {gsave translate 5715 srand 0 3 mt 24 pu procwide { 0.5 3 random 1 sub 0.3 mul rlineto} repeat 26.5 pd procwide { -0.5 3 random 1 sub 0.3 mul rlineto} repeat 3.5 pu closepath gsave 141 setwebtint fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 3.5 mt 5 pu 8 pr 5 pd closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 10.5 mt 4 pu 8 pr 4 pd closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 14.5 mt 5 pu 8 pr 5 pd closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 19.5 mt 5 pu 8 pr 5 pd closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke black 4 2 (|3TEXT 1) cc 4 6.7 (|3APPLESOFT\nPROGRAM\nLINES) cc 4 12.7 (|3HIRES\nPAGE 1) cc 4 18.0 (|3APPLESOFT\nSTRINGS AND\nVARIABLES) cc 4 22 (|3MACHINE\nCODE) cc 4 25.5 (|3DOS) cc -1 3.2 (|1$0800) cr -1 8.2 (|1???? |k) cr -1 10.2(|1$2000) cr -1 14.2 (|1$4000) cr -1 19.2 (|1???? |k) cr -1 24.3 (|1$9600) cr 13 11 (|4START OF\nPROGRAM\nPOINTER SET\nTO $0800) cc 13 18 (|4LOMEM SET\nTO $4000) cc 13 26 (|4HIMEM SET\nTO BOTTOM\nOF MACHINE\nCODE -1) cc % sequence is [ tipx tipy tailx taily tipfat tailfat tipdepth tipspread ] 198 setwebtint [ 8.5 3.5 13 7 0.7 2.5 1.2 2] fattailnw [ 8.5 14.5 13 16.5 0.7 2.5 1.2 2] fattailnw [ 8.5 19.5 13 22 0.7 2.5 1.2 2] fattailnw black 4 -1.5 (|3(C) Applesoft Basic, using HIRES 1) cc grestore } store 4 39 proc1 26 39 proc2 4 6.5 proc3 26 6.5 proc4 21.5 2.5 (|3Fig. 3-4. Usual ways of combining BASIC and machine language programs. Note that\n machine code goes above Applesoft or below Integer. ) cc /text1 (|z|y |1first instruction of an Integer BASIC program. It takes an "illegal" command, butit is easily done with a single POKE command. Should you also be using the HIRES pages, you still start your machine language program at $0800, but |k) store 0 69 text1 cf showpage %%%%%%%%%%%%%%%% page 41- %%%%%%%%%%%%% false setuppage 41 oddheader /text1 (|z|y |1you would most likely reset your LOMEM pointer to one location above the highest HIRES screen location needed. This is shown in Fig. 3-4B. |h|p Applesoft does things quite differently than Integer Basic. The Applesoft programs start at a start-of-program pointer TXTAB and build their way up, while the string variables start at HIMEM and work down. |h It is not normally possible to change the start-of-program pointer during a program since the program is already in memory and not movable. While you can put a machine language program below this pointer, the only way to do it is to change the start pointer before you load your final Applesoft program. |h Note that this start-of-program pointer is not LOMEM! It is called TXTAB and sits at $0067 (low) and $0068 (high), LOMEM in Applesoft is actually in the middle. LOMEM points to the beginning of the variable space and often marks the end of the program lines. |h You will usually put your machine language program above Applesoft by setting HIMEM before you run your Applesoft program. HIMEM may also be set early in the program. Details on this are shown in Fig. 3-4C. |h For more program room, you also have the option of setting HIMEM to one less than the start of your machine language program, and LOMEM to one more than the highest HIRES location in use. The start-of-program pointer remains at $0800. This lets you put program lines from $0800 up through the start of the HI RES page, and place the strings and variables from the top of the HIRES space to the bottom of your code. This is shown in Fig. 3-40. |h So, we see that machine language programs running with Applesoft normally go above HIMEM, while machine language programs running with Integer BASIC normally go below LOMEM. |h You can also play pointer games to tow a short machine language sequence along inside an Integer BASIC or Applesoft program. One method is to put the machine language stuff between two BASIC statements. The parsed code on the first statement is then altered so it jumps over the machine language part to get to the next expected instruction. These pointer schemes are tricky and get hairy if you make any changes, but some authors use them to "protect" their programs or "hide" their fast code. An advantage of this is you can use one cassette loading to enter both machine and BASIC codings. With a disk it is simpler to let one program load the other one with a second disk command. |h Mainframe RAM usually only goes up to 48K. What is in the other 16K of our 64K Apple? Figs. 3-5 and 3-6 complete the picture for us. |h There are sixteen pages located from $COOO through $CFFF that are reserved for I/O. As Fig. 3-5 shows, the bottom half page ($COOO to $C07F) is used for all the screen switches, the push buttons, the paddles, speaker, cassette, keyboard entry, and the keyboard strobe. The next half page ($C080-COFF) is used to pass address locations to each slot. There are sixteen locations reserved for each slot one through seven. |h Above that, we see seven location blocks that are one page of 256 words each. These usually will hold the "control" PROM or ROM for a given card and are addressed as shown. A final 2K space is reserved from $C800 through $CFFF that can be used by any I/O slot that wants it, as long as all the slots take turns, and only one slot is active at a time. |h There is usually very little RAM in the I/O space. These locations are important, though, for they are how we control the on-board things like the screen modes, speaker, paddles, keyboard, and so on. They are also the way we interact with any working card. If a plug-in card is involved with the code you want to tear into, you will have to pin down exactly what codes goes where. ) store 16 69 text1 cf showpage %%%%%%%%%%%%%%%% page 42- %%%%%%%%%%%%% false setuppage 42 evenheader /proc1 {gsave translate 0 0 mt 40 pu 8 pr 40 pd 8 pl closepath gsave 141 setwebtint fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 0 mt 25 pu 8 pr 25 pd 8 pl closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke 24 setwebtint 0.2 setlinewidth 0 2 mt 8 pr stroke 0 4 mt 8 pr stroke 0 7 mt 8 pr stroke 0 10 mt 8 pr stroke 0 13 mt 8 pr stroke 0 16 mt 8 pr stroke 0 19 mt 8 pr stroke 0 22 mt 8 pr stroke 0 25 mt 8 pr stroke black 4 0.7 (|3BUILT IN I/O) cc black 4 2.7 (|3CARD I/O) cc black 4 5.7 (|3SLOT 1\nROM) cc black 4 8.7 (|3SLOT 2\nROM) cc black 4 11.7(|3SLOT 3\nROM) cc black 4 14.7 (|3SLOT 4\nROM) cc black 4 17.7 (|3SLOT 5\nROM) cc black 4 20.7 (|3SLOT 6\nROM) cc black 4 23.7(|3SLOT 7\nROM) cc 4 35.5 (|32K ROM\nOR RAM\nUSABLE BY\nANY SLOT,\nPROVIDED\nTHEY TAKE\nTURNS) cc -1 -0.3 (|1$C000) cr -1 1.7 (|1$C080) cr -1 3.7 (|1$C100) cr -1 6.7 (|1$C200) cr -1 9.7 (|1$C300) cr -1 12.7 (|1$C400) cr -1 15.7 (|1$C500) cr -1 18.7 (|1$C600) cr -1 21.7 (|1$C700) cr -1 24.7 (|1$C800) cr -1 39.7 (|1$CFFF) cr grestore } store 6 21 proc1 /text1 (|p|y |1If we now turn to the uppermost 12K of address space on the Apple, we see that there are six ROM sockets on the Apple mainframe. Each socket can hold a 2K|jx|j8 bytewide ROM or RAM. Fig. 3-6 shows us the usual setup for Integer BASIC or Applesoft machines. A 2K monitor ROM needs the top or $F8 socket. |h There are two possible monitors, the old or absolute reset one, and the newer autostart one.) store /text2 (|p|y |1Continuing down our ROM sockets, Applesoft uses the bottom five, while Integer BASIC uses the middle three, along with an optional programmer's aide that fits in the bottommost or "DO" socket. The uppermost Integer ROM at "F0" also holds the extremely useful mini-assembler code, along with the old floating point package, and the "Sweet 16" 16-bit machine pseudocode. None of these machine language test and debug features are available in the Applesoft ROMs. |h This area is all ROM and cannot normally be written to. But the locations in this area are useful to interact with the monitor or either BASIC language. |h The entire top of the machine can be bypassed by any plug-in card through the INH line. This lets a plug in ROM card give you the choice of either BASIC, or it can let a RAM card do darn near anything it wants to, including running other languages, holding DOS, or giving you extra RAM space.) store 20 32 (|3Fig. 3-5. I/0 map.) cl 0 69 text1 cf 0 18 text2 cf showpage %%%%%%%%%%%%%%%% page 43- %%%%%%%%%%%%% false setuppage 43 oddheader /proc1 {gsave translate 0 0 mt 16 pu 8 pr 16 pd closepath gsave 141 setwebtint fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 0 mt 3 pu 8 pr 3 pd closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 6 mt 5 pu 8 pr 5 pd closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 10 mt 3 pu 8 pr 3 pd closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 13 mt 3 pu 8 pr 3 pd closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke black -1 -0.3 (|1$D000) cr -1 2.7 (|1$D600) cr -1 5.7 (|1$E000) cr -1 9.7 (|1$F400) cr -1 12.7 (|1$F800) cr -1 15.7 (|1$FFFF) cr 4 1.7 (|3PROGRAM\nAIDE) cc 4 4.3 (|3UNUSED) cc 4 8.8 (|3INTEGER\nBASIC\nINTERPRETER) cc 4 11.2 (|3ASSEMBLER) cc 4 14.2 (|3MONITOR) cc 4 -2 (|3(A) Integer BASIC) cc grestore } store /proc2 {gsave translate 0 0 mt 16 pu 8 pr 16 pd closepath gsave 141 setwebtint white fill grestore 0.2 setlinewidth 24 setwebtint stroke { 0 0 mt 3 pu 8 pr 3 pd closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 6 mt 5 pu 8 pr 5 pd closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 10 mt 3 pu 8 pr 3 pd closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke} pop 0 13 mt 3 pu 8 pr 3 pd closepath gsave white fill grestore 0.2 setlinewidth 24 setwebtint stroke black -1 -0.3 (|1$D000) cr -1 12.7 (|1$F800) cr -1 15.7 (|1$FFFF) cr 4 8.8 (|3APPLESOFT\nBASIC\nINTERPRETER) cc 4 14.2 (|3MONITOR) cc 4 -2 (|3(B) Applesoft BASIC) cc grestore } store 23 54 proc1 38 54 proc2 /adj {/txtwide 14.5 store -7 0 translate} store 33 24 17 6 (|/adj |z|y |3You cannot tear a program apart that is not already in the machine and capable of running!) /cf orangebox 33 6 17 6 (|/adj |z|y |3At any given instance, any valid program MUST have everything it needs in the machine so it can continue!) /cf orangebox 25 27 (|/makeblue |-OBVIOUSLY\274) cc 25 9 (|/makeblue |-THEN AGAIN\274) cc % 8.5 1.3 (|;|/makeblue +) cr % zapf? /text1 (|p|y |1Note that many software programs placed on RAM cards may deny you ever gaining access to the monitor ROM in mainframe socket $F8. This can make intercepting a running program rather tricky. |h Many machine language programs will start at $0800 and work their way upwards, but you can expect any program to end up just about anywhere, depending on what other resources of the Apple are being tapped. |h One ultra sneaky trick is to start your machine code at the bottom of the keyboard buffer at $0200, with a jump, and then run up through everything in between there and the end of your machine language program. |h This neatly hides the "real" starting address of your program and also gives you an attractive page One text or LORES display while the rest of the program is loading. You must, of course, find out where the program is before you can attack it. |h Let's start with a very obvious fact\274 ) store /text2 (|p|y |1What this says is that any program that uses a disk may not have that part of the program in which you are interested sitting in the machine at any given time. This rule also says that any program must be placed in the machine exactly where it normally will run, and it must be started off on exactly the first instruction location. |h So, be sure you have that part of the program that you want to analyze in the machine when you attack it. The other side of the coin has the good news\274 ) store /text3 (|p|y |1So, if there is no disk whirring between where you are and what you want to analyze, it all has to be there in the Apple somewhere, somehow. But, where is where? ) store 10 63.5 (|3Fig. 3-6. The high ROM maps.\nA|k plug-in |kROM |kor |kRAM |kcard\ncan deactivate these and\nsubstitute its own code.) cc 16 49.5 text1 cf 16 22 text2 cf 16 4 text3 cf showpage %%%%%%%%%%%%%%%% page 44- %%%%%%%%%%%%% false setuppage 44 evenheader /text1 (|p|y |1You must pin down all of the exact locations a target program uses before you can tear into it. There are at least four good ways to do this\274) store 9.5 53.5 17 13 3.5 (FINDING PROGRAM\nLOCATIONS) ( |h ( ) Read the instructions. |h ( ) Ask DOS to tell you. |h ( ) Infer from use. |h ( ) Empty, then fill the machine.) /cl bluetitbox /text2 (|p|y |1The first and most obvious way is to see if the author did not tell you somewhere just exactly where the program sits. For instance, the loading instructions for the Adam's Adventures 0-12 tell you these go from $OBOO through $57FF and that the starting point is $OBOO. Being told ahead of time where the program starts and resides is the easiest and best method, so always look around carefully for loading information. |h The second way to find where a machine language program goes is to let DOS tell you. On a 4BK machine BLOADed under standard DOS 3.3, the starting address ends up in $AA72 (low) and $AA73 (high). The program length is stashed in $AA60 (low) and $AA61 (high). After loading, you reset, do a call -151 to get into the monitor, and, then, inspect these locations. The old monitor ROM might be needed to force reset back into the monitor. |h DOS can also give you some hints. If you can read the catalog, the type of file and its length should be obvious. Even listening to the number of track clicks during a load should tell you something about how long the program is and which disk tracks it lies on. Take off the disk drive cover, and you can actually watch the drive move from track to track. With some practice, you will be surprised how much this can tell you. |h This process, when formalized, is called boot tracing. where the program sits from what it has to do and what it has to interact with. |h Our HRCG gives us a good example here. We can't directly find where HRCG sits since it is an "R", or relocatable, rather than a "B", or binary file. But, the Applesoft Toolkit book tells us HRCG fits under DOS and moves HIMEM down to protect itself and its alternate character fonts from Applesoft incursion. |h There's a simple and easy-to-use BASIC program called LOADHRCG that comes with the HRCG program. In it is a variable called ADRS which equals HIMEM. Run this one with no alternate character sets, and we see that ADRS ends up as $BDFE. Run it with one alternate character set, and HIMEM moves three pages lower to $BAFE. Two alternate sets and HIMEM drops three more pages lower to $B7FE, and so on. This special example is shown in Fig. 3-7. |h So, by inference, HRCG sits from $BDFF through $95FF. This will include the HRCG action and the bulk file used for character set Zero, the default ASCII set. Other character sets build downward three pages at a time, with the lowestnumbered set on the bottom and the highest set always at the top, again as shown in Fig. 3-7. |h You can find this out on your own by carefully studying a printout of the LOADHRCG Applesoft program and then doing loadings and finding the value of ADDR, otherwise known as HIMEM. The same study should show you how the alternate character sets are filled in. ) store 0 69 text1 cf 0 51 text2 cf showpage %%%%%%%%%%%%%%%% page 45- %%%%%%%%%%%%% false setuppage 45 oddheader /text1 (|p|y |1The final method of pinning down a large program works even if all other methods fail, and should be used as a check even if you are absolutely sure where the target program sits. This final method is a sledgehammer. You empty the machine completely, and then refill it only with your target program . Then, you casually flip through memory, a page at a time, untill you find the program. The next tearing step gives us full details on this\274 ) store /proc2 {gsave translate 5715 srand /procwide 16 store 0 4 mt 10.5 pu procwide { 0.5 3 random 1 sub 0.3 mul rlineto} repeat 14.5 pd 5715 srand procwide { -0.5 3 random 1 sub 0.3 mul rlineto} repeat 7 pu closepath gsave 141 setwebtint fill grestore 24 setwebtint 0.2 setlinewidth stroke 24 setwebtint 0 1 mt 8 pu 0.2 setlinewidth stroke 24 setwebtint 0 1 mt 8 pu 0.2 setlinewidth stroke 0 4 mt 1.5 pu 8 pr 1.5 pd closepath gsave white fill grestore 24 setwebtint 0.2 setlinewidth stroke 0 5.5 mt 1.5 pu 8 pr 1.5 pd closepath gsave white fill grestore 24 setwebtint 0.2 setlinewidth stroke 0 7 mt 1.5 pu 8 pr 1.5 pd closepath gsave white fill grestore 24 setwebtint 0.2 setlinewidth stroke 0 8.5 mt 3 pu 8 pr 3 pd closepath gsave white fill grestore 24 setwebtint 0.2 setlinewidth stroke black 4 2.5 (|3USER RAM) cc 4 4.3 (|3ALT SET 1) cc 4 5.8 (|3ALT SET 2)cc 4 7.3 (|3ALT SET 3) cc 4 9.8 (|3HRCG) cc 4 12.5 (|3DOS) cc -1 3.7 (|1$84FF) cr -1 5.5 (|1$87FF) cr -1 6.7 (|1$8AFF) cr -1 8.2 (|1$8DFF) cr -1 11.2 (|1$9600) cr grestore } store 28.3 46 proc2 /text2 (|p|y |1We have now seen how an Apple's memory is arranged and the methods we need to use to find where a program sits. Let us now go back to the mainstream of our tearing attack. |h You can use any method you like to pinpoint exactly where thyour target program lies. Try reading instruction s, and then try letting DOS tell you. Then, try inference from what the program does and how it interacts with the Apple. If none of that works \274) store /text3 (|p|y |1There is nothing more infuriating than to find out you are really analyzing interpreted BASIC code left over from last Tuesday's 4 AM breakout game, instead of your target program. |h To prevent this from happening, you will want to completely and absolutely empty your machine of everything old and unneeded before you begin. There are two very good reasons for this. One is that you won't be wasting your time analyzing something that is not part of your target program. The second is that an empty machine that has just been filled is one sure way to find or verify the location of your target program. |h You should always clear your Apple of old stuff before attacking a target program. But, how do you empty a machine? |h Even a just repowered Apple will come up with random garbage in most all of the RAM locations. The trick is to load each and every memory location with an obvious value that is very easy to spot, particularly when it is scrolling by. The value $00 is dangerous since it is also a Break command, and it is hard to read on the fly. I use the value $11 instead. On a listing, you will get an unmistakable string of continuous lines on anything that is still empty . This pattern is readable even during an abrupt scroll. |h The following steps show us how to empty your Apple. It' s very easy to do from the monitor. You put a $11 somewhere and, then, move it as far up in memory as you want, recopying it over and over again. If you are using DOS 3.3, you should empty locations $0220 through $03CE, and $0800 through |k) store 16.3 44.5 (|6Fig. 3-7. Location of 48K Apple HRCG program and alternate character sets.) cl 16 31.7 (EMPTY THE MACHINE ) burpleheader 16 69 text1 cf 16 43 text2 cf 16 29.5 text3 cf showpage %%%%%%%%%%%%%%%% page 46- %%%%%%%%%%%%% false setuppage 46 evenheader /text1 (|z|y |1$95FE. Be sure to empty your machine after booting DOS. Do things the other way around and the DOS boot code will return to haunt you. |h|p If you are not using DOS, then you can go ahead and empty $9600 through $BFFF as well. You might also like to empty page One from $0100 to $0180. But, don't try to empty page Zero, the top half of page One, the first few locations of page Two, the top of page Three, or anything above $COOO. Erasing any of these locations will bomb the machine or cause other problems. |h To empty your Apple, put an "empty" symbol in some location. Then, use the monitor to move a block of memory-starting at that location and moving up by one. |h ) store % A good empty symbol is "$11". % A. To empty user RAM except for DOS: % 0800: 11 < cr > % 0801 < 0800.95FEM < cr > % B. To empty all user RAM: %0800: 11 < cr > %0801 < 0800.8FFEM < cr > % C. To empty most of pages $02 and $03: %0220: 11 < cr > %0221 < 0220.03CEM < cr > /text2 (|p|y |1To get into the monitor from either BASIC language, do a CALL -151. Once again, do not try to empty page Zero, the top half of page One, the first few locations on page Two, page Three above $03CF, or anything above $COOO. |h Some target programs will try to prevent you from ever going into the monitor. Switch to the old (nonautostart) monitor ROM if this happens. |h When your machine is empty, snoop around everywhere to see what it looks like. From the monitor, do a 0800.BFFF < cr > and watch the "elevens" go streaming by. |h You'll next want to load and verify the locations of the HRCG program from $8DFF through $95FF. Try adding alternate character sets, one at a time, and see what happens. |h Always start with an empty machine and always return to one anytime you get confused as to what is happening.) store /text3 (|y|p |1After you have emptied the machine and loaded your target program, go ahead and list it. Make two copies on the heaviest white tractor paper you can find. You list a program from the monitor by typing the starting address and, then, the character "L" eighty times and, then, a < cr > . Each L command gets you twenty lines of disassembled code. Use too few L's and you will have to retype them in the middle of your listing. Too many and you simply hit RESET when you get to the end of the target program.) store 0 11(LIST THE PROGRAM) burpleheader 6 55.2 (|3A. To empty user RAM except for DOS:) cl 10 50 15 4 (0800: 11 < cr > |k 0801 < 0800.8FFEM < cr >) /cc orangebox 6 47.3 (|3B. To empty all user RAM:) cl 10 42 15 4 (0800: 11 < cr > |k 0801 < 0800.8FFEM < cr >>) /cc orangebox 6 39.2 (|3C. To empty most of pages $02 and $03:) cl 10 34 15 4 (0220: 11 < cr > |k 0221 < 0220.03CEM < cr >) /cc orangebox 0 69 text1 cf 0 31 text2 cf 0 9 text3 cf showpage %%%%%%%%%%%%%%%% page 47 %%%%%%%%%%%%% false setuppage 47 oddheader /text1 (|p|y |1Keep three clean white pages before and after the listing. Do NOT take the listing sheets apart. Instead, carefully reinforce every tear line, tractor holes and all, with transparent tape. Actually, you would be best off having a welder transcribe a copy of the listing by burning it into a quarter-inch steel plate for you. |y No matter how rugged you make it, it won't be enough. The object here is to keep the listing in one piece and legible after handling and rehandling over and over again. |h So, don't spare the tape. |h Label the top sheet with the name of the target program and the date you started attacking it. Don't forget the year and version number. The second copy is a backup to be used when the first one falls apart or gets totally illegible. |h You will also want to create two copies of a hex dump of your target program. For HRCG, you get in the monitor, type 8DFF.95FF, reach over and move the printer paper up a space or two, and, then, hit < cr> . Incidentally, on both the listings and the hex dump, use the printer's skip-over-margin feature if you have it available. |h Most of our tearing apart will be done on the listing sheets. The hex dump sheets will sometimes show us a pattern in a file or will give us some other pictorial information or other visual clues that can be of enormous help. Yes, you might have to list and hex dump the entire machine for really fancy programs, and this will take bunches of paper and, maybe a ribbon or two. But this isn't nearly as bad as it seems, and it must be done if you are to crack the program. |h Well, we finally have completed our preliminaries. It sure took a long time to get here. Now the fun starts. Ready?) store /adj {-7.3 0 translate} store 25 4.2 17 6 (|/adj ( ) Lots of question marks. ( ) Break commands ($00). ( ) Dumb repetition. ( ) Rare commands in odd mixes. ) /cl orangebox /text2 (|p|y |1Carefully look at your listing. Not for detail, but for overall vibes. Anytime you think something may be helpful, jot it down on one or another of the pads. |h But, once again, do not jump to conclusions and do not attempt to analyze any part of the code in detail. At this stage in the game, we are interested only in the flow and pattern of the big picture. The first thing we want to do is isolate the action so that we can work with it separately. As you go along, you will gain a feel for what I call "rational" code. |h For rational code has a flow to it, with reasonable commands used in reasonable ways. At this point, we don't want to pass judgement nor force conclusions as to what is which. But see if you can't separate obviously "rational" code from everything else. |h Now, we told our lister to lis, assuming that it would be handling working machine language code. The lister will also try to list a file, or random garbage, as if it was rational code. So, we can expect lots of visual clues as to whether we are working on real code or file values. Here are some sure signs\274 ) store 16 32.5 (SEPARATE THE ACTION FROM BULK FILES) burpleheader 16 69 text1 cf 16 30.7 text2 cf showpage %%%%%%%%%%%%%%%% page 48- %%%%%%%%%%%%% false setuppage 48 evenheader /text1 (|p|y |1The question mark means that the lister thought it found an illegal op code, something that the 6502 micro does not know how to use. There are times and places where you will get an occasional question mark in the middle of working and valid code. This has to do with the "lister" getting out of whack on the first instruction, or it may (rarely) be a value or two a programmer has put between working code segments. But, lots of question marks are a good sign of a file. |h The break $00 command is enigmatic. BRK is a debugging tool and one of the most powerful the 6502 microprocessor has available. But, a break command is only rarely allowed to appear in working code as a valid instruction! Why? Because the break command immediately forces a debugging interrupt, or else, it might rarely be used for an error trap or a restart. |h Dumb repetition is another clue. Say you push the processor status on the stack with a PHP command. That's fine. But, why do it fifteen times in a row? That is irrational. As you go along, you will get a feel for what is rational code. |h Do it. Start through ythe HRCG listing. There's a few question marks at the beginning and a few breaks, but mostly it is rational. Chances are these are stashes that go with the code modules. As you go along, you get lots of rational code. Continue. Page after page of rational code. |h Suddenly, around $92DF, things get weird and stay that way, all the way to the end. Lots of question marks, breaks, and dumb code. |h Let's guess and say that our bulk file goes from $92FF to $95FF. It looks like there's some garbage, or a stash below $92FF, but let's speculate. Three pages ring a bell. Check the HRCG Manual and you'll find it takes three pages for an a character set. Apparently, we have the default character set here. We should NOT jump to conclusions this early in the game, nor should we try a detailed analysis of the bulk files, but maybe just a little peek won't hurt\274 |h Check the hex dump for these pages. See the pattern? Every eighth row almost, but not always, is all zeros. Except for the lower case g, p, and a few other exceptions, most characters would leave one dot row out of eight blank. |h Strong evidence. But, not strong enough. Later, we will tear into this bulk file and verify exactly what it does. We will also find out where it starts. For now, draw a bright red line across the listing page between $92FD and $92FF. Label the area below "BULK FILE." On your serendipity pad, sketch something like Fig. 3-8, that shows an HRCG action from $8DFF through $92FE and a bulk file from $92FF through $95FF. ) store /proc1 {gsave translate 0 0 mt 15.5 pu 8 pr 15.5 pd closepath % gsave 141 setwebtint fill grestore gsave white fill grestore 24 setwebtint 0.2 setlinewidth stroke 0 7.5 mt 8 pu 8 pr 8 pd closepath gsave 141 setwebtint fill grestore 24 setwebtint 0.2 setlinewidth stroke black -1 -0.3 (|1$8DFF) cr -1 7.3 (|1$92FF) cr -1 15 (|1$95FF) cr 4 4 (|3ACTION) cc 4 12 (|3BULK\nFILE) cc grestore } store 8 7.5 proc1 23 20 (|4HOLDS DOT PATTERNS FOR THE DEFAULT CHARACTER SET) cl 23 12.5 (|4HOLDS CODE MODULES ACTION AND STASHES USED BY HRCG) cl % fattail [ tipx tipy tailx taily tipfat tailfat tipdepth tipspread ] fattailew 198 setwebtint [ 16.4 19.5 22.5 19.1 1 3 2 2 ] fattailew [ 16.4 11 22.5 11.5 1 3 2 2 ] fattailew black /text2 (|p|y |1Don't worry just yet about the extra question marks we have above the bulk file. Somehow, these look "different" from the code in the bulk file. As you gain practice, any slight differences leap out at you. But, our goal for here and |k) store 4 5.5 (|3Fig. 3-8. Separating the action from the bulk files.) cl 0 69 text1 cf 0 4 text2 cf showpage %%%%%%%%%%%%%%%% page 49- %%%%%%%%%%%%% false setuppage 49 oddheader /text1 (|z|y |1now, is only to separate the action from the bulk files, nothing more. In HRCG, this roughly cuts our task in half. In other programs, the bulk files may be the lion's share of the code.) store /text2 (|p|y |1No matter what code you write or how secretive you are, there is an Achille's heel you have to contend with. This is the 60 RTS or Return From Subroutine command. RTS is our first and foremost attack point into unknown code. It is the chink in the armor, the pry point, the skeleton key. Let's split off the subroutines and watch how fast the code breaks up. |h Go through your code and at every "rational" place that you find a 60 RTS, use a highliter to put a green bar through all of the code except the address. |h Something like this \274 ) store /text3 (|p|y |1Do this for every 60 RTS you see in the action. If you aren't sure whether the 60 is rational or not, then color only the RTS green, rather than the entire line. Generally, question marks below a 60 RTS are allowed; those close above are suspect. |h If you do this on HRCG, you should end up with 35 "definites" that are greenlined all the way across, and one "maybe" located at $8F85 that is only boxed. |h Do not try to analyze any of this code yet. We will let the code analyze itself later on. |h We have just identified the end of every subroutine in the program. |h Since properly written machine language programs will end up mostly subroutines, we already have nearly all our code modules isolated! |h All that with several strokes of a fuzzy green page highliter! |h Now, things start to get interesting\274 ) store /text4 (|p|y |1Next, get yourself an orange page highliter and go through the action. Identify every rational JSR and its address in orange. |h Do this two ways. If the JSR goes to a local address inside the action, paint only the JSR and the address. If the JSR goes out-of-range to some other part of the memory, paint the JSR, the address, and one inch more, and "half" an arrowhead. ) store /adj {6 7.2 translate} store /tabs [6 11] store 0 36 3 (|/adj $8E1E- |t60 |tRTS ) {30 setwebtint 12 7.5 mt 1 setlinecap 1 setlinewidth 34 pr stroke } tractor black 16 63.5 (PAINT ALL SUBROUTINE RETURNS GREEN) burpleheader 16 11 (PAINT ALL SUBROUTINE CALLS ORANGE) burpleheader 16 69 text1 cf 16 62 text2 cf 16 34 text3 cf 16 8.8 text4 cf showpage %%%%%%%%%%%%%%%% page 50- %%%%%%%%%%%%% false setuppage 50 evenheader /adj {6 7.2 translate} store /tabs [6 15] store 0 52.8 3 (|/adj $8E0E- |t20 1F 8E |tJSR 8E1F ) {95 setwebtint 2 20.5 7.5 mt 1 setlinecap 1 setlinewidth 5.5 pr stroke } tractor /adj {6 7.2 translate} store /tabs [6 15] store 0 33.5 3 (|/adj $8E16- |t20 ED FD |tJSR FDED ) {95 setwebtint 20.5 7.5 mt 1 setlinecap 1 setlinejoin 1 setlinewidth 6.5 pr -1.2 1.2 rlineto stroke } tractor /adj {6 7.2 translate} store /tabs [6 15] store 0 6.7 3 (|/adj $8E1F- |tA9 74 |tLDA #$74 ) {95 setwebtint 6 7.5 mt 1 setlinecap 1 setlinejoin 1 setlinewidth 4 pr stroke } tractor /text1 (|p|y |1Like so for a local JSR\274) store /text2 (|p|y |1This subroutine call is in range, so we color only the JSR and the $8ElF. For an out-of-range or "long distance" call, do it like this\274 ) store /text3 (|p|y |1You use the arrowhead to identify an out-of-range call. Should you have a questionable or irrational subroutine call, color only the JSR for now. (The reason for half an arrow is that you might get two arrows side-by-side. If this happens, make one point "up" and the other "down.") |h Orange is a nice color, so let's use it some more. For each local JSR call, find out where the JSR goes, and color the start of that line orange. Go only through the address, starting a quarter inch to the left. For instance, at $8E0E, you have a local call of JSR $8ElF. Go to the start of line 8ElF and do this\274 ) store /text4 (|p|y |1This tells us that we are starting on some "live" and rational code, and that what follows will be a useful and worthwhile worthwhile subroutine. Once again, we do not want to analyze any code just yet. ) store 0 69 text1 cf 0 51 text2 cf 0 32 text3 cf 0 5 text4 cf showpage %%%%%%%%%%%%%%%% page 51- %%%%%%%%%%%%% false setuppage 51 oddheader /adj {6 7.2 translate} store /tabs [6 15] store 0 11 3 (|/adj $8E16- |t20 ED FD |tJSR FDED ) {95 setwebtint 2 21 7.5 mt 1 setlinecap 1 setlinejoin 1 setlinewidth 6 pr -1.2 1.2 rlineto stroke 42.5 7.2 (|3|/makebrown COUT (Output Character) 1) cr } tractor /text1 (|p|y |1Two fine points. If there is already an orange stripe here, or one of another color, just put an orange "ear" or small black dot on the existing stripe. Each new time this happens, add a new black dot. |h This will give you a "popularity poll" of your subroutines. We probably won't use this voting result for our HRCG analysis, but in a large program, the popularity of a subroutine can tell you how important that sub is and how much effort you should spend in understanding it. |h A second possibility is that the JSR seems to go to the middle of an op code, instead of the start. The most likely reason for this is that the lister got off on the wrong foot. See the "WILL THE REAL LISTING PLEASE JUMP OUT" sidebar at the end for details. What happens is that the lister starts off with a value or two in a file and assumes it is a valid part of a program that can be disassembled. Op codes take one, two, or three bytes. If the first byte is wrong, the listing will also be wrong. If you get a "JSR to the middle of\274 ", try relisting from the JSR address to see if you get rational code. This will help clarify the boundaries between stashes and code. We will see an example of this later. |h Should your JSR want to go to your bulk file, you guessed wrong! Either the bulk file has a code module in it, or else your JSR really is a random "20" in a stash somewhere. Pay careful attention to loose ends like this, for pinning down exact code and file beginning addresses can save you hours of frustration. |h After all of your local subroutines are taken care of, try to identify the out-ofrange ones. They must go somewhere. Somewhere is most often a monitor subroutine, or some DOS subroutine or subs in either BASIC. |h Table 3-1 shows us the most popular locations used by the monitor, DOS, and I/O. Try to get a match between Table 3-1 and each out-of-range subroutine call. Label this match with a brown felt-tip pen. We purposely kept this list down to the more popular locations. We may look at Applesoft, Integer BASIC, and DOS internals in a future enhancement. Most user libraries have extensive memory listings if you get into something out of the ordinary. |h For instance, in $8E16, we have a JSR $FDED. A check of Table 3-1 shows us it is one of the most often used monitor routines called COUT. This code takes what is in the accumulator and outputs it as a character. This output goes to whatever is connected to the output hooks. The code should look like this\274) store /text2 (|p|y |1Notice that this immediately tells us that the code module is used to output characters. This very much pins down how the module is used and its place in the big picture. And we still haven't analyzed any code. |h Sometimes a JSR call will point to a different part of user RAM. This usually means that the target program is in more than one piece. Each piece, of course, will eventually have to be dealt with. The Wizard and the Princess is a good example of a program that has code modules all over the lot. ) store 16 69 text1 cf 16 9 text2 cf showpage %%%%%%%%%%%%%%%% page 52- %%%%%%%%%%%%% false setuppage 52 evenheader 3 68 (|3Table 3-1. Important Monitor, DOS, and I/O Locations.)cl 0 25.5 35 40.8 3 /tabs [ 7 12 18 ] store (PAGE $00\nHex Decimal Mnemonic Use |k) (|p|y |h |1$20 |t12 |tWNDLFT |tLeft side of scroll window $21 |t33 |tWNDWTH |tWidth of scroll window $22 |t34 |tWNDTOP |tTop of scroll window $23 |t35 |tWNDBTM |tBottom of scroll window |h $24 |t36 |tCH |tCursor horizontal position $25 |t37 |tCV |tCursor vertical position $21 |t38 |tGBASL |tLORES graphics base low $27 |t39 |tCBASH |tLORES graphics base high |h $28 |t40 |tBASL |tTEXT base address low $29 |t41 |tBASH |tTEXT base address high $2A |t42 |tBA2L |tScroll temporary base low $2B |t43 |tBAS2H |tScroll temporary base high |h $30 |t48 |tCOLOR |tHolds the LORES color value $32 |t50 |tINVFLG |tNormal/Inverse/Flash mask $33 |t51 |tPROMPT |tHolds prompt symbol $34 |t52 |tYSAV |tTemporary Y register hold |h $36 |t54 |tCSWL |tOutput character hook low $37 |t55 |tCSWH |tOutput character hook high $38 |t56 |tKSWL |tInput character hook low $39 |t57 |tKSWH |tInput character hook high |h $45 |t69 |tACC |tAccumulator save $46 |t70 |tXREC |tX register save $47 |t71 |tYREG |tY register save $48 |t72 |tSTATUS |tFlag register save |h $49 |t73 |tSPNT |tStack pointer save $4E |t78 |tRNDL |tKeybounce random number low $4F |t79 |tRNDL |tKeybounce random number high) /cl bluetitbox /tabs [ 7 12 18 ] store 0 2.5 35 20.3 3 (PAGE $03\nHex Decimal Mnemonic Use |k) (|p|y |h |1$03D0 |t 976 |t |tRe-enter DOS $03EA |t1002 |t |tReconnect DOS I/O hooks $03Fo |t1008 |tBRKV |tBreak vector low address $03F1 |t1009 |t |tBreak vector high address |h $03F2 |t1010 |tSOFTEV |tWarm start vector low address $03F3 |t1011 |t |tWarm start vector high address $03F4 |t1012 |tPWRDUP |tWarm start EOR AS checksum $03FS |t1013 |tAMPERV |tApplesoft "&" Jump Code |h $03F8 |t1016 |tUSRADR |tControl Y vector Jump Code $03FB |t1019 |tNMI |tNMI vector Jump Code $03FE |t1022 |tIRQLOC |tInterrupt vector low address $03FF |t1023 |t |tInterrupt vector high address ) /cl bluetitbox showpage %%%%%%%%%%%%%%%% page 53- %%%%%%%%%%%%% false setuppage 53 oddheader 16 68 (|3Table 3-1, cont. Important Monitor, DOS, and I/O Locations.)cl /tabs [ 7 12 18 ] store 14 23 34.5 43.8 3 (PAGE $C0\nHex Decimal Mnemonic Use |k) (|p|y |h |1$C000 |t-16384 |tIOADR |tKeyboard input location $C0l0 |t-16368 |tKBDSTRB |tKeyboard strobe reset $C020 |t-16352 |tTAPEOUT |tCassette data output $C030 |t-16336 |tSPKR |tSpeaker click output |h $C040 |t-16320 |tSTROBE |tGame I/O connector strobe $C050 |t-16304 |tTXTCLR |tGraphics ON soft switch $C051 |t-16303 |tTXTSET |tText ON soft switch $C052 |t-16302 |tMIXCLR |tFull screen ON soft switch |h $C053 |t-16301 |tMIXSET |tSplit screen ON soft switch $C054 |t-16300 |tLOWSCR |tPage ONE display soft switch $C055 |t-16299 |tHISCR |tPage TWO display soft switch $C056 |t-16298 |tLORES |tLORES ON soft switch |h $C057 |t-16297 |tHIRES |tHIRES ON 50ft switch $C058 |t-16296 |t |tAnnunciator 0 OFF soft switch $C059 |t-16295 |t |tAnnunciator 0 ON soft switch $C05A |t-16294 |t |tAnnunciator 1 OFF soft switch |h $C05B |t-16293 |t |tAnnunciator 1 ON soft switch $C05C |t-16292 |t |tAnnunciator 2 OFF soft switch $C05D |t-16291 |t |tAnnunciator 2 ON soft switch $C05E |t-16290 |t |tAnnunciator 3 OFF soft switch |h $C05F |t-16289 |t |tAnnunciator 3 ON soft switch $C060 |t-16288 |tTAPEIN |tCassette tape read input $C061 |t-16287 |tPBO |tPush button 0 input $C062 |t-16286 |tPB1 |tPush button 1 input |h $C063 |t-16285 |tPB2 |tPush button 2 input $C064 |t-16284 |tPDLO |tGame Paddle 0 analog input $C065 |t-16283 |tPDL1 |tGame Paddle 1 analog input $C066 |t-16282 |tPDL2 |tGame Paddle 2 analog input |h $C067 |t-16281 |tPDL3 |tGame Paddle 3 analog input) /cl bluetitbox /tabs [4 8 ] store /adj {0 -0.2 translate} store 23 9.5 15 9.5 3.3 (DISK ACCESS\nQ7 Q6 ACTION ) (|/adj |h clear |tclear |tREAD clear |tset |tSENSE set |tclear |tWRITE set |tset |tLOAD) /cl bluetitbox showpage %%%%%%%%%%%%%%%% page 54- %%%%%%%%%%%%% false setuppage 54 evenheader 6.5 68 (|3Table 3-1, cont. Important Monitor, DOS, and I/O Locations.)cl 3 41.5 36 24 3 /tabs [ 7 12 18 ] store (MORE PAGE $C0\nHex Decimal Mnemonic Use |k) (|p|y |h $C080 |t-16256 |t |tDisk stepper phase 0 OFF $C081 |t-16255 |t |tDisk stepper phase 0 ON $C082 |t-16254 |t |tDisk stepper phase 1 OFF $C083 |t-16253 |t |tDisk stepper phase 1 ON |h $UJ84 |t-16252 |t |tDisk stepper phase 2 OFF $C085 |t-16251 |t |tDisk stepper phase 2 ON $C086 |t-16250 |t |tDisk stepper phase 3 OFF $C087 |t-16249 |t |tDisk stepper phase 3 ON |h $C088 |t-16248 |t |tDisk main motor OFF $C089 |t-16247 |t |tDisk main motor ON $C08C |t-16244 |t |tDisk Q6 CLEAR $C08D |t-16243 |t |tDiskQ6SET |h $C08E |t-16242 |t |tDisk Q7 CLEAR $C08F |t-16241 |t |tDiskQ7 SET ) /cl bluetitbox /tabs [ 7 12 18 ] store 3 1.5 36 37 3 (PAGES F8-$FB\nHex Decimal Mnemonic Use |k) (|p|y |h $F800 |t-2048 |tPLOT |tPlot a block on LORES screen $F819 |t-2023 |tHLiNE |tDrawa horizontal LORES line $F828 |t-2008 |tVLlNE |tDraw a vertical LORES line $F832 |t-1998 |tCLRSCR |tClear full LORES screen |h $F836 |t-1994 |tCLRTOP |tClear top of LORES screen $F847 |t-1977 |tGBASCALC |tCalculate LORES base address $F85F |t-1953 |tNEXTCOL |tIncrease LORES color by three $F864 |t-1948 |tSETCOL |tSet color for LORES plotting |h $F871 |t-1935 |tSCRN |tRead color of LORES screen $F941 |t-1727 |tPRNTAX |tOutput A then X as hex $F948 |t-1720 |tPRBLNK |tOutput three spaces via hooks $F94A |t-1718 |tPRBL2 |tOutput X spaces via hooks |h $FA43 |t-1469 |tSTEP |tSingle step (old ROM only!) $FAD7 |t-1321 |tREGDSP |tDisplay working registers $FB1E |t-1250 |tPREAD |tRead a game paddle $FB2F |t-1233 |tINIT |tInitial i ze text screen |h $FB39 |t-1223 |tSETTXT |tSet up text screen $FB40|t-1216 |tSETGR |tSet up LORES screen $FB4B|t-1205 |tSETWND |tSet text window to normal $FBCl |t-1087 |tBASCALC |tCalculate text base address |h $FBD9 |t-1063 |tBELL 1 |tBeep speaker if ctrl G $FBE4 |t-1052 |tBELL2 |tBeep speaker once $FBF4 |t-1036 |tADVANCE |tMove text cursor right by one $FBFD |t-1027 |tVIDOUT |tOutput ASCII to screen only ) /cl bluetitbox showpage %%%%%%%%%%%%%%%% page 55- %%%%%%%%%%%%% false setuppage 55 oddheader 7.5 45 (|3Table 3-1, cont.\nImportant Monitor,\nDOS, and I/O Locations.)cc 15 31.5 36 39 3 /tabs [ 7 12 18 ] store (PAGES $FC-FD\nHex Decimal Mnemonic Use |k) (|p|y |h $FClO |t|k|k|k-1008 |tBS |tBackspace screen $FC1A |t-998 |tUP |tMove screen cursor up one $FC22 |t-990 |tVTAB |tVertical screen tab using CV $FC24 |t-988 |tVTABZ |tVertical screen tab using A $FC2C |t-980 |tESCl |tProcess escape movements A-G |h $FC42 |t-958 |tCLREOP |tClear text to end of screen $FC58 |t-936 |tHOME |tClear screen and home cursor $FC62 |t-926 |tCR |tCarriage return to screen $FC66 |t-922 |tLF |tLine feed to screen onIy $FC70 |t-912 |tSCROLL |tScroll text screen up one |h $FC9C |t-868 |tCLEOL |tClear text to end of line $FCA8 |t-856 |tWAIT |tTime delay set by accumulator $FDOC |t-756 |tRDKEY |tGet input character via hooks $FD1B |t-741 |tKEYIN |tRead the Apple keyboard $FD35 |t-715 |tRDCHAR |tGet key and process ESC A-F |h $FD62 |t-670 |tCANCEL |tCancel keyboard line entry $FD67 |t-665 |tGETLNZ |tCR, then get kbrl input line $FD6A |t-662 |tGETLN |tGet input line from keyboard $FD6F |t-657 |tGETLNl |tGet kbd input, no prompt $FD8B |t-629 |tCROUTl |tClear EOL then CR via hooks $FD8E |t-626 |tCROUT |tOutput return via hooks |h $FDDA |t-550 |tPRBYTE |tOutput full A in hpxto hooks $FDE3 |t-541 |tPRHEX |tOutput low A in hex to hooks $FDED |t-531 |tCOUT |tOutput character via hooks $FDFO |t-528 |tCOUTl |tOutput character to screen $4E |t-578 |tRNDL |tRandom number low $4F |t-579 |tRNDH |tKeybounce random number high) /cl bluetitbox /tabs [ 7 12 18 ] store 15 1.5 36 27.5 3 (PAGES $FE-$FF\nHex Decimal Mnemonic Use |k) (|p|y |h $FE2C |t-468 |tMOVE |tMove block of memory $FE36 |t-458 |tVERIFY |tVerify block of memory $FE5E |t-418 |tLIST |tDisassemble 20 instructions $FE63 |t-413 |tL1ST2 |tDisassemble A instructions $FE80 |t-384 |tSETINV |tPrint inverse text on screen $FE84 |t-380 |tSETNORM |tPrint normal text on screen |h $FE93 |t-365 |tSETVID |tGrab output hooks for screen $FEB0 |t-336 |tXBASIC |tGoto BASIC, destroying old $FEB3 |t-333 |tBASCON |tGoto BASIC continuing old $FEC2 |t-318 |tTRACE |tStart tracing (old ROM only!) $FECD |t-307 |tWRITE |tSave to cassette tape $FEFD |t-259 |tREAD |tRead from cassette tape |h $FF2D |t-211 |tPRERR |tPrint "ERR" to output hook $FF3A |t-198 |tBELL |tOutput bell via hooks $FF3F |t-193 |tIORESR |tRestore all working register $FF4A |t-182 |tIOSAVE |tSave all working registers $FF59 |t-167 |tOLDRST |tOld reset entry, no autostart $FF65 |t-155 |tMON |tEnter monitor and beep spkr ) /cl bluetitbox showpage %%%%%%%%%%%%%%%% page 56- %%%%%%%%%%%%% false setuppage 56 evenheader /adj {6 7.2 translate} store /tabs [6 14.2] store 0 20.5 3 (|/adj $8DFF- |t20 4c 0E 8E |tJMP 8E0E ) {161 setwebtint 20 7.4 mt 1 setlinecap 1 setlinejoin 1 setlinewidth 26 pr stroke } tractor /adj {6 7 translate} store /tabs [6 15] store 0 2 3 (|/adj $8E0E- |t20 1F 8E |tJSR FDED ) {161 setwebtint 6 7.35 mt 1 setlinecap 1 setlinejoin 1 setlinewidth 4 pr stroke } tractor /text1 (|p|y |1As you tear into your target program, go through each and every subroutine call and find out what it points to. If there are a few mystery locations, wait till later on these. Be sure that you pin down as many subs as you can. |h Now is a good time to start a separate list of which addresses go where. Label this list "Cross References" and show the sources of all subroutine calls. As you go along, any time that one part of the code refers to another part, add it to this list. Once again, do this by hand, even if you have an automatic cross reference and disassembly program available. Eventually, you will want this list in numeric order, but for now, just list addresses as you run across them.) store /text2(|p|h |1 Ready for a new color?|k Get the pink highliter and add a pink line for any absolute JMP code ($40) or relative JMP code ($6C). Draw the pink line all the way across the sheet for in-action jumps starting just beyond the address. Draw the pink line from the machine code to only about an inch past the operand for absolute jumps that go out of the action. Then, end these lines with half an arrowhead like you did with the subroutine calls. |h If the jumps are inside the action, then also put a pink line showing where the jump hopped to, just like you did with the subroutines. The jumper and jumpee may be connected vertically along the left-hand edge, but do this only if the two are less than twenty lines apart. Also "vote" on the most popular jumps, with dots if you see more than one jump going to a single location. Add all jumps to your cross-reference sheet. |h If the jump is outside the action, use Table 3-1 to try and find out where the jump is going to. Then, label the jump using a brown felt-tip pen. Here are the two steps that are involved in pinning down an inside-the-action Jump\274 ) store /text3 (|p|y |1and\274 ) store 0 56 (PAINT ALL ABSOLUTE JUMPS PINK)burpleheader 0 69.5 text1 cf 0 55 text2 cf 0 18.3 text3 cf showpage %%%%%%%%%%%%%%%% page 57- %%%%%%%%%%%%% false setuppage 57 oddheader /adj {6 7.2 translate} store /tabs [6 15] store 0 53 3 (|/adj $9020- |t20 4C 9C |tJMP $FC9C ) {161 setwebtint 2 21 7.5 mt 1 setlinecap 1 setlinejoin 1 setlinewidth 26 pr -1.2 1.2 rlineto stroke 42.5 7.2 (|3|/makebrown COUT (Monitor Clear EOP)) cr } tractor /adj {6 15.2 translate} store /tabs [6 15] store 0 9 4 (|/adj $9208- |tC5 23 |tCMP $23 $920A |t90 11 |tBCC $921D $920C |t2C 65 8E |tBIT $8E65 $920F |t70 08 |tBVS $9219 $9211 |tc6 25 |tDEC $25 $9213 |t21 20 92 |tJSR $9221 $9216 |t4C 70 FC |tJMP $FC70 $9219 |tA5 22 |tLDA $22 $921B |t85 25 |tSTA $25 $921D |t20 24 FC |tJSR $FC24 $9220 |t60 |tRTS ) {206 setwebtint 2 27.3 14.3 mt 1 setlinecap 1 setlinejoin 1 setlinewidth 22.5 pl 10.7 pd 4.5 pr stroke 27 11.9 mt 16.5 pl 4.7 pd 4.3 pl stroke } tractor 16 39(SHOW THE BRANCHES IN BLUE) burpleheader /text1 (|p|y |1An outside-the-action jump looks like this\274 ) store /text2 (|p|y |1Notice what is happening? The flow and structure of our program is rapidly becoming obvious. We already have all sorts of hints as to which part of the action does what. But, we are still nowhere near ready enough to tear into the code. |h On an indirect jump using the ($6C) code, go to the address shown in parentheses and identify this as an indirect address, and show the location that is using it for the indirect jump. Let's hack away at our structure some more\274 ) store /text3 (|p|y |1Get out the blue page highliter and paint each branch (BCC, BCS, BMI, BEQ, BNE, BPL, BVC, BVS, but not BIT or BRK) and its address blue. Then, go to that address and enter a blue line on the left. |h Finally, if the branch is less than twenty lines up or down, show the branch action with a light blue felt-tip pen. Show the direction of each branch, and keep any branch lines from crossing. Here is an example\274) store /text4 (|p|y |1If you find branch lines that try to cross each other, draw the problem line up the right-hand side of the address column or elsewhere as needed. It is very important to be able to glance at the listing and tell immediately which branch goes where.) store 16 69.8 text1 cf 16 51 text2 cf 16 37 text3 cf 16 7 text4 cf showpage %%%%%%%%%%%%%%%% page 58- %%%%%%%%%%%%% false setuppage 58 evenheader /text1 (|p|y |1We are really into our structure now. Here, the arrows jump forward, conditionally skipping part of the code. Often, the arrows will go backwards, outlining a block of code called a loop. The loops visually leap out at you. Check the big one at $9298. Note that there can be more than one tail connected to any given arrow. |h Three refinements. The first thing is to watch out for possibly irrational code. If you are in doubt, paint only the mnemonic blue. The second is to label branches directly to RTS as an RTS, rather than showing the arrows. Finally, very long branches should show each end separately, to keep from getting too many lines on the sheets.) store /text2 (|p|y |1Now, carefully, look over the action and identify each "holistic" and "rational" code module. A code module should have at least one obvious entry point and at least one obvious exit point. Any question marks or lister mixups at the beginning of each module should be resolved so that we can exactly identify the boundary of each code module. |h Then, label carefully in red all the external entry points that you know about, and any locations that the instructions refer to. Our "cold" entry point is apparently "0R" which translates to the first code byte at $8DFF. The "warm" entry point is apparently "3R", or $8E02. |h The version number is at "6R", or $8E05. We see an "0A" here, which apparently stands for version 1.0. The "R" mentioned above may be new to you. The "R" means "relative" and is used with relocatable programs. "0R" is the first byte in the program, regardless of where it sits; "3R" is the third byte, and so on. |h By the way, if some of our example codes don't exactly fit your listing, compare the version numbers. Usually, a different version will move parts of the code up or down a few slots from where they first were. |h Here's what this new stuff looks like \274) store /adj {6 9.2 translate} store /tabs [6 13.5] store 0 13.5 3 (|/adj 8DFF |t4C 0E 8E |tJMP $8EOE 8E02 |t4C 1F 8E |tJMP $8E1F 8E05 |t40A |tASL 8E06 |t4FF |t??? 8E07 |t492 |t??? ) {161 setwebtint 19.5 9.6 mt 27 pr 1 setlinewidth stroke 161 setwebtint 19.5 8.3 mt 27 pr 1 setlinewidth stroke 27 9.2 (|3|/makebrown COLD ENTRY\n|/makebrown WARM ENTRY\n|/makebrown (Version 1.0)) cl } tractor /text3 (|p|y |1Note that the ASL mnemonic is meaningless since we have a very short stash here holding the version number. A mnemonic is only meaningful when applied at exactly the right place in working code. |h While you are labeling outside entry points, be sure to check the top of page Three for warm start, breakpoint, IRQ, NMI, and RESET vectors. These may point to important starting or recovery portions of your code. Many newer programs will RESET to themselves, rather than to the monitor. The RESET and soft start pointers can be a great help in showing you where the "high level" code sits.) store 0 54.3 (SEPARATE THE CODE MODULES FROM THE STASHES) burpleheader 0 69 text1 cf 0 52 text2 cf 0 11.7 text3 cf showpage %%%%%%%%%%%%%%%% page 59 %%%%%%%%%%%%% false setuppage 59 oddheader /text1 (|p|y |1Since HRCG is a utility or a service type of support program, it doesn't mess with the page Three hooks. But this is an exception, so always check. |h OK. Separate all your modules and identify all the external access hooks. Identify everything else that you know for certain from the instructions. What's left in the action consists of code modules as yet undiscovered. Such as dead code, garbage, stashes, or oversights. |h Dead code is code that is never used. Don't throw any away just yet, because it will most likely come to life later. This can happen because you have yet to discover some address entry points or else you have missed coloring something along the way. |h A lot of programmers will leave dead code in their programs so that the next code module or file can start off nice and neat on an even page boundary. Dead code may also be some location that will be written to later by DOS. Dead code will usually be completely rational, but it won't seem to tie in with the rest of the program. |h Do not prejudge garbage. It may become most meaningful later on. Most programmers try to shorten their code as much as possible, so if it looks like lots of garbage is left, chances are you haven't gotten as far as you think. Stashes are short code files that have meaning. We will attempt to identify many of them in the next section. |h And oversights, of course, are your own doing. |h We now should have identified all of the working code modules, and should be able to find most of their access and entry points, their interaction, and their exits. Now, we could actually start to think about tearing into the code. |h But no, not yet. Lots of details still remain. Remember that the longer you hold off on finding out exactly what the code does, the easier the job will get, and the less of it you will have to do. |h Let's see what the stashes and files have to say\274) store /text2 (|p|y |1We have a sort of a chicken-and-egg problem. We can't tell yet what the files are up to since we don't know yet how the program works. And, since we don't know how the program works, it can't tell us what the files are up to. |h Fortunately, there are several file filters you can apply that can isolate most of the stashes and bulk files and tell you their meaning and intended use. Crack your files and you have made a tremendous progress. |h Even if you can only crack a few files now, doing so is definite progress, and allows moving bytes from the unknown to the known. This is very much like a big jigsaw puzzle. Not only does each piece fit somewhere, but it also gets removed from the pile of unknown remaining pieces. This makes identifying and using the rest of the pieces easier since there are now less of them. |h Let's isolate all the rational code modules and assume that everything left is a stash. Things may not be nearly this simple, but let's try it anyway. Fig. 3-9 shows us the remaining stash locations. |h When you think you have a stash identified, put a narrow yellow stripe up the extreme right-hand margin, going over the tractor holes. Eventually, you want to end up with a continuous wide line up and down the right-hand side, wide yellow for fully known and understood stashes, and wide green for fully known and understood code modules. When the last of the white right margin disappears, you have conquered your target program.) store 16 28.8 (IDENTIFY FILES AND STASHES ) burpleheader 16 69 text1 cf 16 28 text2 cf showpage %%%%%%%%%%%%%%%% page 60-%%%%%%%%%%%%% false setuppage 60 evenheader /proc1 {gsave translate % 0 2 mt 34 pu 8 pr 34 pd closepath 141 setwebtint fill 0 3.5 mt 3.5 pu 8 pr 3.5 pd closepath gsave 141 setwebtint fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 14 mt 3.5 pu 8 pr 3.5 pd closepath gsave 141 setwebtint fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 21 mt 8.5 pu 8 pr 8.5 pd closepath gsave 141 setwebtint fill grestore 0.2 setlinewidth 24 setwebtint stroke 0 0 mt 35.5 pu 8 pr 35.5 pd closepath 24 setwebtint 0.2 setlinewidth stroke % 0 5 mt 8 r 0 10.5 mt 24 setwebtint 8 pr stroke 0 32.5 mt 24 setwebtint 8 pr stroke 0 31 mt 24 setwebtint 10 8 black 4 2 (|3USER\nSUB FILE) cc 4 5.5 (|3CODE\nMODULE) cc 4 9 (|3ASCII\nHEADER FILE) cc 4 12.5 (|3WORKING\nFLAG FILE) cc 4 16 (|3CODE\nMODULE) cc 4 19.5 (|3ADDRESS\nFILE) cc 4 26 (|3CODE\nMODULES) cc 4 31.2 (|3HIRES\nBASE FILE) cc 4 33.5 (|3GARBAGE) cc -1 -0.3 (|1$8DFF) cr -1 3.3 (|1$8E0B) cr -1 6.8 (|1$8E42) cr -1 10.3 (|1$8E5F) cr -1 13.6 (|1$8E73) cr -1 16.5 (|1$8F48) cr -1 20.7 (|1$8F7D) cr -1 29.3 (|1$92DF) cr -1 32.3 (|1$92EB) cr -1 34.8 (|1$92FE) cr grestore } store 6.5 34.5 proc1 17 50 (|3Fig. 3-9. Separating HRCG stashes from the code modules.) cl /text1 (|p|y |1We see a two-slot stash at $8E05, and then another obvious one starting at $8E42 on your listing. But wait. The "vibes" of our stash change dramatically at $8E5F. Let's assume we have a second stash starting there. Put a brown dotted line all the way across between $8E5C and $8E5F to remind us we think we have two separate files. The second stash apparently ends with $8E73, since $8E74 holds what looks like rational code, even though this code doesn't seem to be isolated yet. |h We have a long stash starting at $8F48, obviously consisting of lots of question marks and the patently excessive use of BCC branches to dumb places. Where does this stash end? It's not obvious at first, but let's guess that it ends with $8F81. The code starting at $8F82 (that we aren't supposed to be reading yet) says to put something in $8E60 and then return. This is rational thinking, particularly since $8E60 is a slot in another stash and it might end up as a flag in a flag file. |h Another stash starts at $92DF, identified by lots of zeros. Again, notice a change of vibes at $92EB. The first twelve locations are in three groups of four each and all end in zero. The remainder of the stash is strange. Let's call it two separate stashes and, once again, add a dotted brown separation line. |h Now comes the tricky part. First, we want to guess what each location in each stash is used for, and, then, we want to nail each location down for sure. |h To do this, make yourself up some file and stash filters. A stash filter is some test for some pattern that makes sense to you and to the particular target program you are attacking. The filter is valid if its answer leaps out at you and is then clinched by some independent test. ) store 0 32 text1 cf showpage %%%%%%%%%%%%%%%% page 61 %%%%%%%%%%%%% false setuppage 61 oddheader /text1 (|p|y |1Normally, you will have to design these filters yourself. Do so very carefully. Your choice of filters will vary with the target program and how long it is. Here are some obvious filters to try first\274 ) store 26 51 17 14 3 (|h STASH AND BULK FILE FILTERS) ( ( ) Is it something obvious? ( ) Is it an ASCII string? ( ) Is it a table of addresses? ( ) Is it a group of flags? ( ) Is it a conversion table? ( ) Is it DOS related? ( ) Does it fill a program need?) /cl bluetitbox /text2 (|p|y |1These are the usual filters I try first and the order in which I try them. The HRCG is very accommodating in its stash uses. The early tests will tell you a lot about each stash. Other programs may not be so easy. |h We attack the chicken-and-egg problem this way. First, we filter the stashes and bulk files as best as we can to find out as much about them as we are able. |h Then, we take this information back to the code modules and see what new thing this tells us about the modules. Then, we look into the modules and see what they tell us about the remaining unknown files. |h Three or so trips round and around and we should have things pinned down fairly well. Now, if you are into an Adventure or something else really heavy with stashes and bulk files, it won't be this simple, but file filtering always makes a very good starting point toward further understanding. |h Let's try these filters one by one and see what they tell us. One example of an obvious file is any code on a display page. This might be $0400-$07FF for text or LORES page One, $0800-0BFF for the less common text or LORES page Two, $2000-3FFF for HIRES page One, or $4000-$5FFF for HIRES page Two. |h If any of these pages are in use, the bytes stored here have to correspond to the image on the screen. |h Note that the screen images will change as the program is used. What you see is the code for the display pages at the exact point in the program where you did your listing. Chances are that text page One got messed up by the listing process itself. |h Besides their obvious location, the HIRES color bytes tend to be mostly $00, $2A, $55, $7F, $80, $AA, $D5, and $FF bytes. In HRCG, we can often ignore these for a while, since they are the result of the program and not a part of it. |h Another example of obvious code happens when you are reading interpreted BASIC statements. We'll save details on this for another time. But note that the byte patterns in BASIC are distinctive, starting with a line number, the location of the next program line, and, then, followed by a parsed code using token keywords and ASCII symbols, and, finally, ending up with an end-of-statement symbol. |h You can check into the LOADHRCG Applesoft program for a quick example. Do this by hex dumping machine code starting at $0800. |h Usually, the BASIC code tells you you are looking in the wrong place. But, |k) store 16 49 text2 cf 16 69 text1 cf showpage %%%%%%%%%%%%%%%% page 62- %%%%%%%%%%%%% false setuppage 62 evenheader /text1 (|z|y |1machine language is sometimes stuffed inside BASIC programs and, at other times, it will interact directly with the BASIC statements. This happens in the case of fast sort routines, variable locators, cross-reference programs, and so on. |h As a much simpler and shorter example of an obvious file, look at $8E06. It is two bytes long. Is it an address? The address is $92FF. Is there anything special about $92FF? There sure is! This is the location of the start of the bulk file that we think is an alternate character set. Since we obviously need a pointer like this and since a pointer would be early in the program, let's assume this stash is the pointer to the character set start. |h Make sure any "obvious" evidence is very strong. Don't make wild guesses, and don't make too many guesses at once. Above all, don't force things to fit your pet theories about what a stash "has" to be. In this case, guessing an address and having that address reinforce our guess is reasonable. |h Next, try some ASCII filters. The ASCII code is the standard way of stashing letters, numbers, and punctuation in your Apple. Table 3-2 shows us the ASCII code. An ASCII-coded stash will be mostly code starting with $CX or $DX, will have a few $AO spaces, and will often end with a $8D carriage return. |h This assumes, as most Apple programmers do, that the ASCII most-significant bit is set to a 1. If the MSB is not set, then an ASCII file will be mostly values in the forties and fifties, with a $20 for each space, and with a $0D carriage return ending. If the file is mostly lower case, then the code will be mostly "EX" and "FX" values for a set MSB and "sixties" and "seventies" for a cleared MSB. |h The actual display code used by the Apple on its upper-case-only old text screen differs slightly from ASCII. This code is shown in the Apple manual. The code provides for no control characters and offers normal, inverse, and flashing upper-case-only characters. |h Programmers rarely use this viIdeo display code inside their programs. Instead, they usually will use ASCII, and set and clear the flashing and inverse flag (location $0032) as needed. The video display code can only be written directly to the screen and must not be output to any other device via the output hooks. |h The code would get used in a program only if the text display needs a wildly changing mix of flashing, inverse, and normal characters, and, then, only if the upper-ease-only text screen is the only intended output. |h Note that ASCII text is automatically converted to video display code by the usual monitor routines as it goes onto the screen. |h Now, any file will give you some message back if you filter it for ASCII. The key test is whether the message says anything meaningful. You can ASCII filter all your stashes and bulk code, but it pays to pick only the most promising first. |h In the case of the HRCG, we see that the stash beginning at $8E42 looks the most promising. ASCII filter this code and you get\274) store /text2 (|p|y |1This is obviously the prompt message that first appears under HRCG. The odds of it being anything else are insanely small. |h Note as you "crack" a stash, that it no longer belongs to the unknown. Further, a cracked stash will greatly simplify tearing apart the actual code, for we can now assume the code module directly above it on the listing will be involved in printing out this message. |h As you get practice, you'll be able to immediately spot stashes and bulk files that will yield useful messages under ASCII code. Be sure to do this by hand a few times until you get the feel of this powerful filter. ) store 0 69 text1 cf 0 12.5 text2 cf 24 14.3 (|3|/makebrown HI-RES CHAR GEN VERSION 1.0) cr showpage %%%%%%%%%%%%%%%% page 63- %%%%%%%%%%%%% false setuppage 63 oddheader /text1 (|p|y |1We may look at some short and powerful ASCII "snoop" programs in a future enhancement. Commercial programs that list ASCII strings can also be used. But, watch out that loading the snoop program doesn't bomb part or all of your target code. For now, do your ASCII snooping by hand untill you can spot an ASCII file at a casual glance. |h The acid test of an ASCII filter is whether you get a message back or not. Once again, don't force things. If the filter doesn't hit you over the head with the answer, try something else. |h If the message seems fragmented or disjointed, possibly you are looking at an area that gets written repeatedly by DOS putting message upon message on top of each other. A copy of the key buffer from $0200-$02FF may also look the same way. In either case, you are far more interested in the use of this file, rather than its contents. |h Our next trial stash filter should answer the question, "Do we have a list of addresses?" Look at the stash starting at $8E5F. A bunch of zeros, with a $92FF in it. Recall that 92FF points to the start of the default character generator. Do we have a file of alternate character sets here? |h It doesn't look like it, but those zeros suggest a test. Let's run the HRCG and, then, let's load nine alternate character sets. Then, we will see how and if this stash changes. |h Try it and there's no change! This should teach us several things. First, always be sure you have what you think you have in the machine. Second, be sure and try any trick you can think of, even if it doesn't work. |h Third, and most importantly, NEVER force anything to fit your pet theories. The address filter clearly fails on this file. More on this stash in later. |h Let's try an address filter on the next stash starting at $8F48. Every second entry is either a $8F or a $90. Look at it on the hex dump and the addresses leap out at you. Color every second address pair yellow on your hex dump. |h Note that the addresses sit backwards on the dump, with the high byte second and the low byte first. This low-byte-first style is typical of most 6502 machine language |k) store 16 44 text1 cf black 24 69 (|3Table 3-2. ASCII Code) cc /asblock { save /ssnap exch store /vposn exch store /curarray exch store 10.5 0 translate curarray { 0 exch vposn exch cc 2.5 0 translate } forall ssnap restore} store /fakebar {0 2 0.2 sub mt 1.1 pu line2 stroke } store % gets around gonzo command /proc1 {gsave translate 0 0 mt 22 pu 50 pr 22 pd closepath 173 setwebtint fill 0 0 mt 22 pu 50 pr 4.3 pd 42 pl 17.7 pd closepath 167 setwebtint fill 0 18 mt 4 pu 8 pr 4.3 pd closepath 161 setwebtint fill black font9 gsave 0 -0.3 translate [(NUL) (SOH) (STX) (ETX) (EOT) (ENQ) (ACK) (BEL) (BS) (HT) (LF) (VT) (FF) (CR) (SO) (SI) ] 16 asblock [(DLE) (DCl) (DC2) (DC3) (DC4) (NAK) (SYN) (ETB) (CAN) (EM) (SUB) (ESC) (FS) (GS) (RS) (US)] 14 asblock [((SPACE)) (!) (") (#) ($) (%) (&) (') (\() (\)) (*) (+) (,) (\261) (.)(/) ] 12 asblock [(0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (:) (;) (<) (=) (>)(?) ] 10 asblock [(@) (A) (B) (C) (D) (E) (F) (G) (H) (I) (J) (K) (L) (M)(N)(O) ] 8 asblock [(P) (Q) (R) (S) (T) (U) (V) (W) (X) (Y) (Z) ([) (/) (])(^)(_)] 6 asblock [(`) (a) (b) (c) (d) (e) (f) (g) (h) (i) (j) (k) (l) (m) (n)(o) ] 4 asblock [(p) (q) (r) (s) (t) (u) (v) (w) (x) (y) (z) (\{) (|/fakebar) (\}) (-) (DEL) ] 2 asblock grestore font3 [(0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (A) (B) (C) (D) (E) (F) ] 18.5 asblock gsave 2.2 9 translate 90 rotate 0 0 (|3UPPER HEX BYTE) cc grestore gsave 0 -0.3 translate 5 16 (0 or 8) cc 5 14 (1 or 9) cc 5 12 (2 or A) cc 5 10 (3 or B) cc 5 8 (4 or C) cc 5 6 (5 or D) cc 5 4 (6 or E) cc 5 2 (7 or F) cc grestore 30 20 (|3LOWER HEX BYTE) cc white 4 19.3 (|-ASCII) cc grestore } store 0 46 proc1 showpage %%%%%%%%%%%%%%%% page 64- %%%%%%%%%%%%% false setuppage 64 evenheader /adj {6 7.2 translate} store /tabs [6 14] store 0 13 2 (|/adj $8F7D- |t91 BO |tSTA (BO) , Y $8F7F- |t24 A9 |tBIT $A9 $8F81- |t80 |t??? $8F82- |t8D 60 8E |tSTA $8E60 $8F85- |t60 |tRTS ) { } tractor /adj2 {-10 -0.3 translate} store 5 30 23 9 (|/adj2 $9046 + 1 = $9047, an immediate RTS. $8F7D + 1 = $8F7E, a royal mess $8FA9 + 1 = $8FAA, the start of a subroutine! $8FD1 + 1 = $8FD2, the start of a subroutine! $8FEC + 1 = $8FED, the start of a subroutine! $901A + 1 = $901B, the start of a subroutine ) /cl orangebox /text1 (|p|y |1It looks like we definitely have a table of addresses. For the clincher, check to see if the addresses all go somewhere rational! |h And we have another surprise! Each and every address goes right in the middle of the code all right, but each one seems to point to an extremely dumb place! |h Let's break our rule on tearing into code for a moment and see what code we find immediately above this address table. In this code module, we take a value, multiply it by two and, then, use it as an X index to get the high address in $8F3C. This high address gets shoved onto the stack. Then, we get the low address at $8F40 and shove it onto the stack also. |h Then, we return from the subroutine. What we have really done is we have faked an indirect jump to the selected module. |h Now, what does a subroutine return do? It pops the stack twice and goes to the address it thought it came from. Only we just changed that with the address low and address high stack pushes. |h Note that two pushes and two pops left the stack exactly where we started. Our new code module is, therefore, at the same level that we were before, so we have done an indirect jump, rather than a JSR. |h Ah! But, a subroutine return does not return to the address on the stack. It returns to the address on the stack |/makeblue |3plus one!|1|/makeblack This quirk is from the 6502 Programming Manual. Now, let's try adding one to each address and see what results \274 ) store /text2 (|p|y |1Keep this detective work up, and we find that each address, except for the first two, points to a subroutine. The first one, an immediate return, looks as if it is a mistake. What about the royal mess? Here is a classic example of our lister getting off on the wrong foot. Right now, the lister says \274 ) store /text3 (|p|y |1We know the first part of this is wrong, since we have stashed addresses and not working code here. We suspect the end of the listing may be right, since it seems rational. Our problem address is trying to point to $8F7E, so let's let it do so. |h Relist things starting with $8F7E, and you get ...) store 0 69 text1 cf 0 28 text2 cf 0 10.5 text3 cf showpage %%%%%%%%%%%%%%%% page 65 %%%%%%%%%%%%% false setuppage 65 oddheader /adj {6 7.5 translate} store /tabs [7 14] store 0 60 2 (|/adj $8F7E- |tBO 24 |tBCS $8FA4 $8F80- |tA9 80 |tLDA #$80 $8F82- |t8D 60 BE |tSTA $8E60 $8F85- |t60 |tRTS ) { } tractor /text1(|p|y |1And this is a nice and rational little subroutine. Our problem mess was solved by making sure our lister had something worth listing as its first entry. |h Wow, what a bit of detective work. Our filter has found 27 addresses that lie in the middle of our code, all of which point to valid and workable subroutines, except for the first one that immediately returns. |h Let's carry this further to see what an address stash will tell us about those subroutines. Now, 27 is one more than 26, the number of letters in the alphabet. Look at the ASCII code given back in Table 3-2, and we see a sequence of @ABCDEF\274 that jumps out at you. If the program was using a pointer that started with @ for a 00 value, we would have 27 values, the last 26 of which would be the alphabet in order. Naturally, @ wouldn't be used, so it would immediately return. |h Let's take a wild guess that @ = Address 0, A = Address 1, B = Address 2, and so on. Now, let's see if this heads to any place that is useful. |h Back to the HRCG manual. We have two sets of A to Z commands. This strongly suggests trying to fit the menu selections to the subroutines we already have. Right now, this is sort of a wild guess. But, if it works, and if we can prove it absolutely, we will have chopped mucho time off of our target-program attack. |h Let's look further. Put a brown arrow at each subroutine's starting address that we think does something from A to Z. We get strong reinforcement right off the bat since all of them start off on a new code module. We also notice something rather strange. Each and every module starts off with BCS or BCC. |h Odd. |h But, remember that there are two alphabets needed in HRCG, one for the main menu selection and one for the option selection. Let's continue, since everything has been reinforced so far. |h Apparently each subroutine is a subroutine pair, one of which handles the "main" menu selection and one of which handles the "option" menu selection. Further, the condition of the carry flag tells us which way to go. |h Which is which? To find out, we'll need more detective work. Note that we have a function selection "E" but no option selection "E". Note also that we have an option selection "R", but no function selection "R". Go to the sixth address on the list (E is the sixth character starting with @), and we see a BCS to RTS. Apparently a cleared carry is a function and a set carry is an option. |h Even more important, look at that monitor subroutine clear-to-end-of-screen leaping out at you at $9028 on your program listing. This is a solid and completely independent check on what these addresses are used for. |h As a final check, we look at entry "R" (the fourteenth address), and we see a BCC to RTS, verifying that the carry flag decides which alphabet to use. The code at "R" should "Reverse the overlay" for us. A quick look at this code |k ) store 16 58 text1 cf % 0 32 text2 cf showpage %%%%%%%%%%%%%%%% page 66 %%%%%%%%%%%%% false setuppage 66 evenheader /text1 (|z|y |1shows it setting two flags for us-another confirmation. This confirmation is much weaker than the first one, but support is support.|p |h So, go through all your code addresses and label their uses with a brown felt-tip pen. Use fairly large letters. $8F7E should be labeled "(A) function SELECT N". Check the BCS branch location and the code starting at $8FA4 gets labeled "(A) option PAGE1 PRIMARY". |h Continue through the list. The modules that use the cleared carry are functions, and the ones that use a set carry are options. |h Note the power of the address filter. We now know the meaning and use of well over half of the code modules, without tearing into the code at all. HRCG is very friendly with its menu-driven selections. In other programs, you may not be able to immediately tell one address-code module from another. But the very fact that you can break up the modules into little chunks is extremely valuable and a major time saver. |h The usual clue to filtering address tables is that every second entry is the same and the backwards entry pairs seem to be working through a range in a usually increasing order. The HRCG stash at $8F48 seems to be the only table of addresses we have, so we will try some new filters. |h Our next trial stash filter asks, "Do we have a group of flags? A flag is some location that the program refers to so that it can decide what it is going to do next. In the HRCG, we can expect flags for the display page, the primary page, the working alternate character-set base address, the display mode, and so on. In an "adventure" program, the group of flags can show what is in which room, whether the giant armadillo is asleep or awake, whether the golden clockwork canary can be wound, and similar conditional things. |h A flag file will often be mostly zeros, with a few FF's thrown in here and there. Other hex bytes in a flag file may have only a single bit set, such as $01, $02, $04, $08, $10, $20, $40, and $80. Flag files may also hold an occasional address or two. |h One very good way to verify a flag file is to find some stash that looks reasonable, and then lightly scan nearby code modules to find if there are references to these locations. In the HRCG, we see a likely file starting at $8ESF. A check through some of the option code shows lots of them working with locations $8ESF through $8E73. |h There's usually a two-step process involved in understanding a flag file. First, you prove the flag file is there and checking into the variables of the program in the next section, you attempt to put specific meaning onto every flag. |h Pinning down flag meanings can be quite a challenge. The original programmer started with his flag definitions and locations and, then, built his program around them. You have to do the opposite, taking strange code and inferring what the flags originally stood for. |h Our "Is it a conversion table?" filter is one that takes some experience to use. A conversion table relates addresses to data in some manner. Table lookup is a very fast way to do things, compared to calculating values. The stash starting at $92DF "looks" somewhat like a conversion table that somehow "seems" to be involved with HIRES (high resolution) base addresses. We'll keep this one a "maybe" for now. |h Other examples of conversion tables are the shape tables and sprite maps used in HIRES graphics. A shape table holds a bunch of drawing directions, as needed, to directly write on the HIRES screen, using Apple's graphics routines. A sprite map will hold an image of what is to be remapped onto a HIRES screen. A character from an HRCG character-set file is a sprite map example. ) store 0 69 text1 cf showpage %%%%%%%%%%%%%%%% page 67 %%%%%%%%%%%%% false setuppage 67 oddheader /text1 (|p|y |1Let's continue down the file filter list. Many machine language programs create their own DOS, or else, use DOS variations for protection, access, and so on. In these cases, there are some 005 filters you can apply to your stashes. |h These DOS filters do not seem to help us here on the HRCG. A file involving DOS may consist of bunches of code always ending in $XO or $X8. These are used in the DOS nibble encoding. DOS code modules will often use header constants of $D5, $AA, $96, markers of $DE, $AA, $EB, and a trailer of $DE, $AA, and $EB. These values will jump out at you once you tune yourself into them. DOS code will also repeatedly use LDA $C08C,X commands, followed by a BNE back to itself. "X" here is the slot number. This looks real dumb when you first see it, but it is a sure sign of DOS read activity. |h Another way to filter a file is to ask, "Does it fill an obvious program need?" You'll have to design suitable filters for each and every target program. Let's take a closer look at our bulk file and see what we can find out about it from its structure alone. |h Visual clues can help bunches here, such as the frequency of repetition of some marker. In Zork, the vocabulary file has a zero and, then six bytes, over and over again. The "objects" file takes nine bytes and is in the form of seven flags and an address. Look for these patterns. Break up a file into several smaller files whenever you see any change in these patterns. |h Even if you don't have the foggiest idea about what is in the file or how it is used, deduce as much as you can about the file structure, for this will be a great help later. |h We suspect our bulk file is a default character set. All right. That means that the bits should look like characters if you arrange them just right. We know the characters are arranged in 7 X 8 squares from the ANIMATRIX program. So, a reasonable "Does it fill a program need?" filter on this bulk file is making sure to look at each and every bit and see if there is some visual pattern that looks like character dots. Let's start at $9FOO\274 ) store /text2 (|p|y |1Now, that one is singularly uninformative. Yet, it is the first character and we know that the first noncontrol character in ASCII is a space. Let's try another one at $9307\274 ) store 16 69 text1 cf 16 19 text2 cf /wdot {gsave translate 0 0 0.4 0 360 arc gsave white fill grestore black line1 stroke grestore} store /bdot {gsave translate 0 0 0.4 0 360 arc gsave 205 setwebtint fill grestore black line1 stroke grestore} store /bdot {gsave translate 0 0 0.4 0 360 arc gsave 204 setwebtint fill grestore black line1 stroke grestore} store /pat14 { gsave translate 0 0 (|9($14) \261) cl 6 0.2 wdot 7 0.2 wdot 8 0.2 bdot 9 0.2 wdot 10 0.2 bdot 11 0.2 wdot 12 0.2 wdot grestore} store /pat0 { gsave translate 0 0 (|9($00) \261) cl 6 0.2 wdot 7 0.2 wdot 8 0.2 wdot 9 0.2 wdot 10 0.2 wdot 11 0.2 wdot 12 0.2 wdot grestore} store /pat04 { gsave translate 0 0 (|9($04) \261) cl 6 0.2 wdot 7 0.2 wdot 8 0.2 wdot 9 0.2 wdot 10 0.2 bdot 11 0.2 wdot 12 0.2 wdot grestore} store /pat08 { gsave translate 0 0 (|9($08) \261) cl 6 0.2 wdot 7 0.2 wdot 8 0.2 wdot 9 0.2 bdot 10 0.2 wdot 11 0.2 wdot 12 0.2 wdot grestore} store /pat22 { gsave translate 0 0 (|9($22) \261) cl 6 0.2 wdot 7 0.2 bdot 8 0.2 wdot 9 0.2 wdot 10 0.2 wdot 11 0.2 bdot 12 0.2 wdot grestore} store /pat3E { gsave translate 0 0 (|9($3E) \261) cl 6 0.2 wdot 7 0.2 bdot 8 0.2 bdot 9 0.2 bdot 10 0.2 bdot 11 0.2 bdot 12 0.2 wdot grestore} store gsave 28 21 translate 0 9.8 pat0 0 8.4 pat0 0 7.0 pat0 0 5.6 pat0 0 4.2 pat0 0 2.8 pat0 0 1.4 pat0 0 0 pat0 grestore gsave 28 5 translate 0 9.8 pat08 0 8.4 pat08 0 7 pat08 0 5.6 pat08 0 4.2 pat08 0 2.8 pat0 0 1.4 pat08 0 0 pat0 grestore showpage %%%%%%%%%%%%%%%% page 68 %%%%%%%%%%%%% false setuppage 68 evenheader /wdot {gsave translate 0 0 0.4 0 360 arc gsave white fill grestore black line1 stroke grestore} store /bdot {gsave translate 0 0 0.4 0 360 arc gsave 204 setwebtint fill grestore black line1 stroke grestore} store /pat14 { gsave translate 0 0 (|9($14) \261) cl 6 0.2 wdot 7 0.2 wdot 8 0.2 bdot 9 0.2 wdot 10 0.2 bdot 11 0.2 wdot 12 0.2 wdot grestore} store /pat0 { gsave translate 0 0 (|9($00) \261) cl 6 0.2 wdot 7 0.2 wdot 8 0.2 wdot 9 0.2 wdot 10 0.2 wdot 11 0.2 wdot 12 0.2 wdot grestore} store /pat8 { gsave translate 0 0 (|9($08) \261) cl 6 0.2 wdot 7 0.2 wdot 8 0.2 wdot 9 0.2 bdot 10 0.2 wdot 11 0.2 wdot 12 0.2 wdot grestore} store /pat22 { gsave translate 0 0 (|9($22) \261) cl 6 0.2 wdot 7 0.2 bdot 8 0.2 wdot 9 0.2 wdot 10 0.2 wdot 11 0.2 bdot 12 0.2 wdot grestore} store /pat3E { gsave translate 0 0 (|9($3E) \261) cl 6 0.2 wdot 7 0.2 bdot 8 0.2 bdot 9 0.2 bdot 10 0.2 bdot 11 0.2 bdot 12 0.2 wdot grestore} store gsave 12 53.1 translate 0 9.8 pat14 0 8.4 pat14 0 7.0 pat14 0 5.6 pat0 0 4.2 pat0 0 2.8 pat0 0 1.4 pat0 0 0 pat0 grestore gsave 12 28.0 translate 0 9.8 pat8 0 8.4 pat14 0 7 pat22 0 5.6 pat22 0 4.2 pat3E 0 2.8 pat22 0 1.4 pat22 0 0 pat0 grestore /text1 (|p|y |1Now, that looks like an exclamation point, the second printing ASCII character. But, things are still weak. Let's try to predict a quote for the next one, starting at $930F. |h And, sure enough\274 ) store 0 69 text1 cf /text2 (|p|y |1Apparently the characters are in the character file in order, just like they go on the screen. Only, we may be jumping to conclusions. Let's try several more characters. |h There are 96 characters, each of which takes up 8 bytes, so we can expect 768 bytes total, or exactly 3 pages. |h Thus, we would expect the numbers and punctuation to start at $92FF, the upper-case alphabet at $93FF, and the lower-case alphabet at $94FF. |h To prove this, we would expect a capital" A" to be at $93FF + $08 = $9407. Try it, and lo and behold\274 ) store /text3 (|p|y |1So, obviously, we know everything that we should know about the bulk file now, right? |h Wrong! |h One very important rule\274 ) store /text4 (|p|y |1Always, check things as independently and as completely as you can before convincing yourself that something is so. |h In the case of our bulk file, the surprise comes on the next character.) store 0 51.1 text2 cf 0 25.8 text3 cf 0 10.2 text4 cf 28 17 (|/makeblue |7THE FINAL SURPRISE IS |/makeblue THAT THERE ARE NO |/makeblue MORE SUPRISES!) cc /adj {-7.5 -0.3 translate} store 3 12 17 7.5 (|/adj |y No matter where you are in cracking a file, there is ALWAYS one surprise remaining between where you think you are and where you really are. ) /cl orangebox showpage %%%%%%%%%%%%%%%% page 69 %%%%%%%%%%%%% false setuppage 69 oddheader /wdot {gsave translate 0 0 0.4 0 360 arc gsave white fill grestore black line1 stroke grestore} store /bdot {gsave translate 0 0 0.4 0 360 arc gsave 204 setwebtint fill grestore black line1 stroke grestore} store /pat14 { gsave translate 0 0 (|9($14) \261) cl 6 0.2 wdot 7 0.2 wdot 8 0.2 bdot 9 0.2 wdot 10 0.2 bdot 11 0.2 wdot 12 0.2 wdot grestore} store /pat0 { gsave translate 0 0 (|9($00) \261) cl 6 0.2 wdot 7 0.2 wdot 8 0.2 wdot 9 0.2 wdot 10 0.2 wdot 11 0.2 wdot 12 0.2 wdot grestore} store /pat1C { gsave translate 0 0 (|9($00) \261) cl 6 0.2 wdot 7 0.2 wdot 8 0.2 bdot 9 0.2 bdot 10 0.2 bdot 11 0.2 wdot 12 0.2 wdot grestore} store /pat02{ gsave translate 0 0 (|9($00) \261) cl 6 0.2 wdot 7 0.2 wdot 8 0.2 wdot 9 0.2 wdot 10 0.2 wdot 11 0.2 bdot 12 0.2 wdot grestore} store /pat8 { gsave translate 0 0 (|9($08) \261) cl 6 0.2 wdot 7 0.2 wdot 8 0.2 wdot 9 0.2 bdot 10 0.2 wdot 11 0.2 wdot 12 0.2 wdot grestore} store /pat22 { gsave translate 0 0 (|9($22) \261) cl 6 0.2 wdot 7 0.2 bdot 8 0.2 wdot 9 0.2 wdot 10 0.2 wdot 11 0.2 bdot 12 0.2 wdot grestore} store /pat3E { gsave translate 0 0 (|9($3E) \261) cl 6 0.2 wdot 7 0.2 bdot 8 0.2 bdot 9 0.2 bdot 10 0.2 bdot 11 0.2 bdot 12 0.2 wdot grestore} store /pat1E { gsave translate 0 0 (|9($1E) \261) cl 6 0.2 wdot 7 0.2 wdot 8 0.2 bdot 9 0.2 bdot 10 0.2 bdot 11 0.2 bdot 12 0.2 wdot grestore} store gsave 27 58.5 translate 0 9.8 pat1E 0 8.4 pat22 0 7.0 pat22 0 5.6 pat1E 0 4.2 pat22 0 2.8 pat22 0 1.4 pat1E 0 0 pat0 grestore gsave 27 42 translate 0 9.8 pat1C 0 8.4 pat22 0 7 pat02 0 5.6 pat02 0 4.2 pat02 0 2.8 pat22 0 1.4 pat1C 0 0 pat0 grestore /imagelocaldirectory (C:/Users/don/Desktop/Tearing/) store % sin fwd slashes for win /imageremotedirectory (http://www.tinaja.com/images/) store % sin fwd slashes for chrome /imageurl imageremotedirectory (spicket1.jpg) mergestr store % goto remote image /imagelocalsource imagelocaldirectory (spicket1.jpg) mergestr store % comes from local file 21 6 % page translate ( data for jpegimageprocwithlink ) 285 285 % hpixels and vpixels 0.1 0.24 mul % photoscale imagelocalsource % local jpg source imageurl % image url on clickthru jpegimageprocwithlink /text1 (|p|y |1Uh - whoops. That's a B all right, but why is it backwards? All the rest are obviously frontwards, aren't they? Let's try the next character\274 ) store /text2 (|p|y |1Hmmm\274 The "C" is also backwards. But why would some characters be frontwards and some backwards? |h They wouldn't. |h Apparently all of the characters are "backwards" with the least-significant bit going out to the display first and the most-significant bit going out to the display last. Think about this for a while and you'll remember that a backwards entry is also how all of the HIRES color routines work, so we should have expected something like this. |h Fig. 3-10 shows us the final arrangement of the default character set in the bulk file. We can safely assume that all other character sets will behave the same way, even though they are located elsewhere in memory. |h Now, a visual bit-by-bit check of a long file may turn out to be totally worthless. But, it also may be a sure clue that will permit quickly cracking most of the program code. It all depends on the program and how creative your cracking approach is. |h What you have to do is make up a "Does it fill a program need?" filter that might show you something. But, keep trying things that are geared to the target program until something leaps out at you and hits you over the head. |h There is one ultimate file filter\274 ) store 16 55.5 text1 cf 16 40 text2 cf 30.5 5.5 16 7.5 2 (THE ULTIMATE FILE FILTER) (Fill the file with water and see where it leaks.) /cl bluetitbox showpage %%%%%%%%%%%%%%%% page 70- %%%%%%%%%%%%% false setuppage 70 evenheader %%%%%%% north tail, west tip %%%%%%% /fattailnw { gsave aload pop /tipspread exch store /tipdepth exch store /tailfat exch store /tipfat exch store /taily exch store /tailx exch store /tipy exch store /tipx exch store /enthu 0.28 store /deltaxn tailx tailfat 2 div sub tipx tipdepth add sub enthu mul store /deltaxs tailx tailfat 2 div add tipx tipdepth add sub enthu mul store /deltaye taily tipy tipfat 2 div sub sub enthu mul store /deltayw taily tipy tipfat 2 div add sub enthu mul store tipx tipy mt tipx tipdepth add tipy tipspread 2 div add lineto tipspread 2 div tipfat 2 div sub pd tipx tipdepth add deltaxn add tipy tipfat 2 div add tailx tailfat 2 div sub taily deltayw sub tailx tailfat 2 div sub taily curveto tailfat pr tailx tailfat 2 div add taily deltaye sub tipx tipdepth add deltaxs add tipy tipfat 2 div sub tipx tipdepth add tipy tipfat 2 div sub curveto tipspread tipfat sub 2 div pd closepath fill grestore } store % sequence is [ tipx tipy tailx taily tipfat tailfat tipdepth tipspread ] /procwide 16 store /twoplot { gsave translate 0 4 mt 7 pu procwide { 0.5 3 random 1 sub 0.3 mul rlineto} repeat 12 pd 5715 srand procwide { -0.5 3 random 1 sub 0.3 mul rlineto} repeat 7 pu closepath gsave 141 setwebtint fill grestore 24 setwebtint 0.2 setlinewidth stroke /b1 {mt 1 pu 1 pr 1 pd closepath black fill } store gsave 0 1.5 translate 0 0 mt 8 pu 8 pr 8 pd closepath white fill black line1 [{0 0 mt 8 pu stroke} 1 9 ] xrpt [{0 0 mt 8 pr stroke} 1 9 ] yrpt 2 6 b1 3 6 b1 4 6 b1 5 6 b1 6 6 b1 2 5 b1 3 4 b1 4 3 b1 5 3 b1 6 2 b1 2 1 b1 6 1 b1 3 0 b1 4 0 b1 5 0 b1 black 12 8 (|/makeblue |3THAT'S\n|/makeblue A "2") cc % sequence is [ tipx tipy tailx taily tipfat tailfat tipdepth tipspread ] 198 setwebtint [8.5 3 12 6.3 0.5 1.7 1 2.5] fattailnw black 0 10.2 (|1MSB) cc 8 10.2 (|1LSB) cc -0.5 0 (|1$938F) cr -0.5 7(|1$9396) cr grestore 0.2 setlinewidth 24 setwebtint 0 0.5 mt 10 pu stroke 8 0.5 mt 10 pu stroke grestore } store 21 40 twoplot /proc1 {gsave translate 0 0 mt 33 pu 8 pr 33 pd closepath 30 setwebtint 0.2 setlinewidth stroke [1 0.5] 0.25 setdash [{0 1.5 mt 8 pr stroke} 0.1 9]yrpt [] 0 setdash 0 11 mt 8 pr stroke 0 22 mt 8 pr stroke black 4 7 (|3NUMBERS\nAND\nSYMBOLS) cc 4 17.5 (|3UPPER\nCASE\nLETTERS) cc 4 28 (|3LOWER\nCASE\nLETTERS) cc -1 -0.4 (|1$92FF) cr -1 10.5 (|1$93FF) cr -1 21.5 (|1$94FF) cr -1 32.5 (|1$95FF) cr grestore } store 7 34 proc1 %%%%%%% west tail, north tip %%%%%%% /fattailwn { gsave aload pop /tipspread exch store /tipdepth exch store /tailfat exch store /tipfat exch store /taily exch store /tailx exch store /tipy exch store /tipx exch store /enthu 0.28 store /deltaxn tipx tipfat sub tailx sub enthu mul store /deltaxs tipx tipfat add tailx sub enthu mul store /deltaye tipy tipdepth sub taily tailfat 2 div sub sub enthu mul store /deltayw tipy tipdepth sub taily tailfat 2 div add sub enthu mul store tipx tipy mt tipx tipspread 2 div sub tipy tipdepth sub lineto tipspread 2 div tipfat 2 div sub pr tipx tipfat 2 div sub tipy tipdepth sub deltayw sub tailx deltaxn add taily tailfat 2 div add tailx taily tailfat 2 div add curveto tailfat pd tailx deltaxs add taily tailfat 2 div sub tipx tipfat 2 div add tipy tipdepth sub deltaye sub tipx tipfat 2 div add tipy tipdepth sub curveto tipspread tipfat sub 2 div pr closepath fill grestore } store %%%%%%% west tail, east tip %%%%%%% /fattailwe { gsave aload pop /tipspread exch store /tipdepth exch store /tailfat exch store /tipfat exch store /taily exch store /tailx exch store /tipy exch store /tipx exch store /enthu 0.28 store /deltax tipx tipdepth add tailx sub enthu mul store tipx tipy mt tipx tipdepth sub tipy tipspread 2 div add lineto tipspread 2 div tipfat 2 div sub pd tipx tipdepth sub deltax sub tipy tipfat 2 div add % debug tailx deltax add taily tailfat 2 div add % debug tailx taily tailfat 2 div add curveto tailfat pd tailx deltax add taily tailfat 2 div sub % debug tipx tipdepth sub deltax sub tipy tipfat 2 div sub % debug tipx tipdepth sub tipy tipfat 2 div sub curveto tipspread tipfat sub 2 div pd closepath fill grestore } store % fattail [ tipx tipy tailx taily tipfat tailfat tipdepth tipspread ] fattailne 198 setwebtint [ 25 38.5 21 34.5 1 1.1 1.5 3 ] fattailwn [ 21 34.5 15.5 36 1.1 2 0 0 ] fattailwe black /textx (|z|y |1FORMULA TO FIND ANY CHARACTER |h |3STARTING ADDRESS = $92FF + 8 * (ASCII - $20) |h (|1WHERE |3ASCII|1 = HEX ASCII VALUE OF CHARACTER) |h EACH CHARACTER IS STORED AS EIGHT SEQUENTIAL BYTES. THE |3FIRST|1 BYTE HOLDS THE DOTS FOR THE |3TOP|1 ROW OF THE CHARACTER. THE LSB OF EACH BYTE IS THE |3LEFTMOST|1 DOT ON THE CHARACTER. THE MSB IS USED FOR OPTIONAL SHIFT OR COLOR CHANGE AND IS NOT DISPLAYED. THE BOTTOM BYTE IS USUALLY BLANK. EXCEPT FOR LOWER CASE DESCENDERS. ) store save /txtwide 27 store 16 66.5 textx cf restore 1.5 31.5 (|3Fig. 3-10. How the HRCG character set is stored in the bulk file.) cl /text1 (|p|y |1If all else fails, and you are making reasonable progress elsewhere in your attack, try changing some or all of the contents of a file and see what changes take place in the program. |h Usually, the program will bomb on random file changes. But, by finding out where and when it bombs and, then, zeroing into one or two locations in our target file, we can sometimes find out lots of things in a hurry. |h Suppose we didn't know our bulk file was an alternate character set. If you made the first eight bytes all $FF's instead of $OO's, then all the spaces in any message would be white boxes, but nothing else would change. Now, this would immediately tell you that the file was a character set and that the first entry was a space. |h Another neat example of this is to go through the movable object file in an Adam's Adventure and change all the room numbers to $FF. You are now carrying everything! |h The only unexplained file left in HRCG is the stash starting at $92EB. Now, this code seems downright weird and has failed all the other tests. The code could be garbage since it is at the very end and since the character generator sets all have to start at the same base address. |h Fill this file with $FF's and what happens? Nothing. There is no change in any part of HRCG that is immediately obvious. So call it garbage. At this point, you should have all your stashes and all your bulk files separated and many of them fully identified. ) store 0 28 text1 cf showpage %%%%%%%%%%%%%%%% page 71 %%%%%%%%%%%%% false setuppage 71 oddheader /text2 (|p|y |1Start a fresh page on your quadrille pad and head it "LIST OF VARIABLES." Now, go through the code modules line by line, and each time you find an address used for loading, storing, BIT testing, logic operations, or whatever, paint the variables pink and the constants green. |h Note that the constants will always have a # symbol in front of them. Page Zero addresses will be two hex digits but no #. Absolute addresses will be four hex digits, again with no #. |h As an example, an LOA $05 puts what is in page Zero memory location $0005 into the accumulator. This is a variable. It is a variable since the contents of $0005 can have any of 256 values ranging from $00 through $FF. |h But, an LOA #$05 puts the value hexadecimal $05 into the accumulator. This is a constant equal to "five" of something. Watch for that # symbol! It will get you every time if you ignore it. |h Our first code module starts at $8ElE. Your variable and constant lines should look like this\274 ) store /text3 (|p|y |1As you identify variables and constants, you can start tearing into code. But, if something isn't immediately obvious, go on elsewhere. Our first object here is getting a list of all locations that will get used for target-program variables. However, if we can find the meanings at the same time, we are just that much further ahead. |h The code starting at $8ElF is very easy to read. First, we set the input hook to $8E74 and, then, we set the output hook to $8F18. Next, we reconnect DOS to internalize these hooks. Then, we switch to the full graphics and pick the HIRES mode. Continuing, we restore the default display parameters and, then, we switch on the graphics mode. Finally, we exit. |h How did we figure all that out? Look back at what we know about these variables\274 ) store /text1 (|p|y |1Back to the code modules\274) store 16 65.5 (ATTACK VARIABLES AND CONSTANTS) burpleheader 16 69 text1 cf 16 63.5 text2 cf 16 30.5 text3 cf /adj {6 6.5 translate} store /tabs [13 20] store 0 33 2 (|/adj 8E1F- A9 74 |tLDA $#74 |t|/makebrown |3(Low address 74)|9 8E21- 85 38 |tSTA #38 |t|/makebrown |3(KSWL) |9 ) { gsave 161 setwebtint 1 setlinewidth 1 setlinecap 1 setlinejoin 25 4.3 mt 6 pl stroke 125 setwebtint 25 5.6 mt 6 pl stroke grestore } tractor /adj {-11.8 -0.3 translate} store 24 3 27 11.5 (|/adj |y $38 and $39 \261 are the KSW switches in the monitor. $36 and $37 \261 are the CSW switches in the monitor. $03EA \261 is the DOS reconnect hook. $C052 \261 is the full screen switch. $C057 \261 is the HIRES switch. Sub $9158 \261 is named "Restore Default Parameters." Sub $9000 \261 is named "Display Primary." $C050 \261 is the GRAPHICS switch. ) /cl orangebox 18 10.2 (|/makeblue |7FROM TABLE 3-1 |/makeblue OR PREVIOUS |/makeblue RESULTS) cc showpage %%%%%%%%%%%%%%%% page 72 %%%%%%%%%%%%% false setuppage 72 evenheader /text1 (|p|y |1Usually, you won't be so lucky on your first try. We now understand that this code module is the initialize portion of HRCG. We also now see what it does. We add all the above variables to our variables list, and color everything that we understand reasonably well pink for a variable or green for a constant. |h Since this module is so obvious, we can also color the right tractor margin a solid wide green. |h We also found out something new. All keyboard inputs go to $8E14 and all character outputs go to $8F18. So, label these locations in red. Do this and two more large code modules now have labels. Call these KEYBOARD ENTRY and CHARACTER OUTPUT. |h Continue through the code modules and identify every variable. If you can tell exactly what the variable is used for, so much the better. If not, just put the variable on the list. The variable will most likely crop up later in another code module that may clarify its use. |h Don't go overboard on analyzing code. If something is obvious and simple, go ahead and crack the code. If it is not, just record all the variables. Do not color any variable or constant till you understand what it is used for. But, be sure to get all of them on the list. |h Pay particular attention to variables inside parentheses. A set of parentheses means that you are doing a jump indirect or using one of the indexed indirect |k) store /tabs [ 5 11] store 3 2 31.5 37.5 2 ( ADDRESS MEMONIC USE |k ) (|y |/makeblue |3-page $00-|1 $0020 |tWNDLFT |tLeft end of scrolling window $0021 |tWNDWDTH |tWidth of scroll ing window $0022 |tWNDTOP |tTop of scrolling window $0023 |tWNDBOT |tBottom of scrolling window $0024 |tCH |tText screen cursor horizontal $0025 |tCV |tText screen cursor vertical $0028 |tBASL |tText screen base address low $0029 |tBASH |tText screen base address high $002A |tBAS2L |tDot row HIRES base address low $002B |tBAS2H |tDot row HIRES base address high $0035 |tYSAV1 |tTemporary Y register save $0036 |tCSWL |tCharacter output hook low $0037 |tCSWH |tCharacter output hook high $0039 |tKSWL |tKeyboard input hook low $004E |tKSWH |tKeyboard input hook high $004F |tRNDL |tKeyboard delay low $00EB |tRNDH |tTemporary X register save $00EC |t |tHIRES base address low $00ED |t |tHIRES base address high $00EE |t |tCharacter set base address low $00EF |t |tCharacter set base address high $00FF |t |tTemporary accumulator save |h |/makeblue |3-page $01-|1 $0104 |t |tJSR stack source pointer (,X) |h |/makeblue |3-page $03-|1 $03EA |t |tHook to reconnect DOS ) /cl bluetitbox 0 41.0 ( |3Table 3-3 List of Variables for HRCG) cl 0 69 text1 cf showpage %%%%%%%%%%%%%%%% page 73 %%%%%%%%%%%%% false setuppage 73 oddheader /tabs [ 5 11] store 19 68.7 (|3Table 3-3 Cont. List of Variables for HRCG) cl 16 3 30 64 2 ( ADDRESS MEMONIC USE |k ) (|h|y |/makeblue |3-page $8E-|1 |h $8E06 |t |tDefault character set base low $8E07 |t |tDefault character set base high $8E08 |t |tjumpto user sub A $8EOB |t |tJump to user sub B $8E42 |t |tPointer to header message $8E5F |t |tEscape key flag $8E60 |t |tAlternate character set flag $8E61 |t |tPrimary page flag $8E62 |t |tInverse video flag $8E63 |t |tTransparent video flag No.1 $8E64 |t |tTransparent video flag No.2 $8E65 |t |tScrolling flag $8E66 |t |tCase flag $8E67 |t |tCharacter set in use base low $8E68 |t |tCharacter set in use base high $8E69 |t |tSave of $8E61 while block mode $8E6A |t |tSave of $8E62 while block mode $8E6B |t |tSave of $8E63 while block mode $8E6C |t |tSave of $8E64 while block mode $8E6D |t |tSave of $8E65 while block mode $8E6E |t |tSave of $8E66 while block mode $8E6F |t |tSave of $8E67 while block mode $8E70 |t |tSave of $8E68 while block mode $8E71 |t |tBlock mode flag $8E72 |tCH |tHorizontal cursor position $8E73 |tCV |tVertical cursor position $8F48 |t |tFunction address file base low $8F49 |t |tFunction address fi Ie base high |h |/makeblue |3- page $92-|1 |h $92DF |t |tStart of HIRES pointerfile $92FF |t |tDefault character fi Ie start |h |/makeblue |3-page$C0-|1 |h $C000 |tIOADR |tKeyboard ASCII input $C010 |tKBDSTRB |tKeyboard strobe reset $C052 |tMIXCLR |tFull graphics soft switch $C054 |tLOWSCR |tPage 1 soft switch $C055 |tHISCR |tPage 2 soft switch $C057 |tHIRES |tHIRES soft switch $C050 |tTXTCLR |tGraphics soft switch |h |/makeblue |3- page $FC-|1 |h $FC22 |tVTAB |tVertical tab from CV sub $FC24 |tVTABZ |tVertical tab from accumulator $FC42 |tCLEEOP |tClear to end of page sub $FC58 |tHOME |tHome text screen monitor sub $FC70 |tSCROLL |tScroll text monitor sub $FC9C |tCLREOL |tClear to end of line sub ) /cl bluetitbox showpage %%%%%%%%%%%%%%%% page 74 %%%%%%%%%%%%% false setuppage 74 evenheader /text1(|z|y |1modes. These are among the most powerful commands the 6502 micro has available, so it pays to very carefully understand how these are used. |h|p It really gets challenging when you get into the double or even triple indirect file manipulations that are involved in the longer Adventure programs. |h Don't worry too much about fuzziness and loose ends. Identify what you can and crack what code you can, but keep moving! And, every time you get a new piece of checkable information, go back and plug it in everywhere it seems to fit. The ripple effect when you do this is often astounding. |h Ourflag file bytes get identified as you go along. Note that $8FA4 puts a $20 in $8E61 to display the primary page and that $8FCC puts a $40 in $8E61 to display the secondary page. We can then conclude that $8E61 is the page flag. |h You can continue this reasoning for the other flags. The block mode ends up using the bottom half of the flag file. ) store /text2 (|p|y |1You should end up with a complete list of all variables, some of the code completely cracked, and lots of new hints that will help you elsewhere in your attack. |h After your list is nearly complete, recopy it legibly in numeric order. Table 3-3 shows a list of the variables used in HRCG. Use this as an example. |h Next, go back through the code. Every code line that uses an implied addressing mode should be painted yellow once you understand it. Implied mode instructions use a single op code byte and are not qualified by a value or an address. Examples are INX, DEY, TXA, CLD, SEC, TSX, and so on. |h If you happen to have code that uses the stack to hold a value for you, this will show up with a PHA, some operations, and, then, a restoring PLA. Show these in yellow just like any other implied instruction. But if, and only if, the PHA and PLA are irrevocably paired as a temporary store, connect them with a yellow bracket. |h Like this\274 ) store 0 47 (PAINT THE HOUSEKEEPING YELLOW ) burpleheader 0 69 text1 cf 0 44.5 text2 cf /adj {6 19.5 translate} store /tabs [13 ] store 0 4 4 (|/adj 8E87- Bl 2A |tLDA ($2A) ,Y 8E89- 48 |tPHA 8E8A- E6 4E |tINC $4E 8E8C- DO OB |tBNE $8E99 8E8E- E6 4F |tINC $4F 8E90- CA |tDEX 8E91- DO 06 |tBNE $8E99 8E93- 49 7F |tEOR #$7F 8E95- 91 2A |tSTA ($2A),Y 8E97- A2 50 |tLDX #$50 8E99- 2C 00 CO |tBIT $COOO 8E9C- 10 EC |tBPL $8E8A 8E9E- 68 |tPLA 8E9F- 91 2A |tSTA ($2A),Y 8EA1- BA |tTSX ) { gsave 35 setwebtint 1 setlinewidth 1 setlinecap 1 setlinejoin 25 17.5 mt 8 pl 13.3 pd 8 pr stroke 25 1.8 mt 6 pl stroke 25 12.6 mt 6 pl stroke grestore } tractor showpage %%%%%%%%%%%%%%%% page 75 %%%%%%%%%%%%% false setuppage 75 oddheader /text1 (|p|y |1Once you understand how a yellow line is used, add comments in brown to explain it. Should you get paired PHP and PLP commands, these should also get bracketed in yellow, but only if they always work together. |h What you are after here is to have a color on each and every line, a comment on each and every line, and, on the right margin of the page, a solid green area for each module that is understood, and a solid yellow area for each stash that is cracked. ) store /text2 (|p|y |1Where you are right now depends on your experience and how tough and how long the program is. If you try this method on a target program that is only a few hundred words long, you should be done by now. You should not only have met your limited goal, but should have the rest of the entire program completely cracked. |h ) store /text3 (|p|y |1Hopefully, you will know what to do next at this point. Go on your own vibes in the most obvious direction. |h On longer programs, the chances are there is lots of white space remaining. These white spaces point to uncracked code and unbroken stashes and bulk files. |h The next step is to write a script. Explain in people-type words what each and every known stash, bulk file, and code module does. |h A complete script of HRCG appears in Table 3-4. Use this as an example. If you have to leave blanks for now, do so. |h Obviously, all machine language programs are different. Some will involve themselves a lot with DOS. Others will use only the HIRES screens for game actions. Still others will interact with a host BASIC program, and so on. |h What you now want to do is customize the attack to fit the program. How you do this is up to you. Here are some things I sometimes try\274 ) store /adj {-6.8 -0.3 translate} store 25 1.5 18 24 (|/adj |y ( ) Look for built-in diagnostics. ( ) Use breakpoints. ( ) Try flowcharting. ( ) Attack indirect addressing. ( ) Add hooks. ( ) Gain partial control. ( ) Use the cassette. ( ) Single step and trace. ( ) Chip away at it. ( ) Attack the fundamental subs. ( ) Ask for help. ( ) Use partial boots. ( ) Detect changes. ( ) Alter files. ( ) Put program on an assembler. ( ) Attack a similar program. ( ) Decipher special codes. ( ) Try something easier.) /cl orangebox 16 58 (WRITE A SCRIPT) burpleheader 16 47.5 (CUSTOMIZE YOUR ATTACK) burpleheader 16 69 text1 cf 16 56 text2 cf 16 45.5 text3 cf showpage %%%%%%%%%%%%%%%% page 76 %%%%%%%%%%%%% false setuppage 76 evenheader /col2 {/xpos 10 store /ypos 64 store} store % huh align? 0 1 33.5 67 2 ( ADDRESS COMMENTS |k ) ($8DFF \261 |h $8E02 \261 |h $8E05 \261 |h $8E06-$8E07 \261 |h $8E08-8E09 \261 |h $8E0B-8E0C \261 |h $8E08-8E1E \261 |h $8E42-8E5C \261 |h $8E42-8E73 \261 |/col2 |3Hard entry point.|1 Clears screen and prints header, connects HRCG hooks. |h |3Soft entry point.|1Connects HRCG but does not clear screen. |h |3Version number|1 x 10. |h |3Base address|1 of default character generator set. Defaults to $92FF. |h |3User subroutine A|1 starting address called by option Y. Defaults to subroutine return RTS. |h |3User subroutine B|1 starting address called by option Z. Defaults to subroutine return RTS. |h |3Hard entry routine. |1Sets I/O hooks, then reconnects DOS. Switches to HIRES full screen. Restores DOS and default parameters. Displays primary. Switches to graphics. |h |3Stash|1 holding ASCII-coded title and version. Used during cold entry. |h |3Stash holding all working flags|1- |h $8E5F - $80 if previous key ESC $00 otherwise $8E60 - $80 if alternate characters $00 if defau It characters $8E61 - $20 if page 1 primary $40 if page 2 pri mary $8E62 - $00 if normal video $7F if inverse video $80 if overstrike video $CO if complement video $8E63 - $80 if transparent mode $00 otherwise $8E64 - $60 if transparent mode $00 otherwise $8E65 - $00 if scrolling $FF if wraparound $8E66 - $00 if caps lock $80 if lower case $CO if single capital $8E67 - Base add low of set in use $8E68 - Base add high of set in use |h $8E69 - Save of $8E61 while block $8E6A - saveof$8E62 while block $8E6B - saveof$8E63 while block $8E6C - Save of $8E64 while block $8E6D - Save of $8E65 whi Ie block $8E6E - Save of $8E66 while block $8E6F - Save of $8E67 whi Ie block $8E70 - Save of $8E68 while block ) /cl greentitbox black 0 69 (|3Table 3.4 Complete script of HRCG.) cl showpage %%%%%%%%%%%%%%%% page 77 %%%%%%%%%%%%% false setuppage 77 oddheader /col2 {/xpos 10 store /ypos 59.7 store} store % huh align? 16 3 33.5 65 2 ( ADDRESS COMMENTS |k ) ( |h $8E74-8EAC \261 |h $8EAD-8F17 \261 |h $8F18-8F27 \261 |h $8F4S-8F7D \261 |h $8FS6-8FA3 \261 |h $8FA4-8FA9 \261 |h $SFAA-8FCB \261 |h $8FCC-8FD1 \261 |h $8FD2-8FDE \261 |h $8FE2-8FEC \261 |h $8FED-900C \261 |h $900D-901A \261 |h $901B-9022 \261 |/col2 $8E71 - $00 if normal display $FF if in block mode $SE72 - CH horizontal position $SF73 - CV vertical position |h |3Enter HRCG via keyboard hook|1. Save A, X, BASH, and BASL. Debounce keyboard and flash cursor till key is pressed. Reset keyboard strobe. |h |3Check keyboard for ESC or CR|1. If a CR, process via sub $92SD. If an ESe, process I, L K, M for cursor motions. Then, clear EOL if E or clear EOS if F. Process A, B, e, and D cursor motions. |h |3Enter HRCG via output hook|1. Save A, X, and Y. If a number and preceded by ESC, change characterset number via $SFS6. If a control command, clear Carry if a function and set Carry if an option. If a letter from @ to Z, process by getting address from stash $8F4S and doing an indirect jump. |h |3Stash of 27 addresses|1 for menu selections A-F. Selection @ does an immediate RTS. Address picked by $8F28. |h |3Function A|1. Alternate character set. If a number from 0-9, calculate new base address and store in $8E67. |h |3Option A|1. Put #$20 in flag $8E61 to switch to primary page 1. |h |3Function B|1. Begin block display if not already there. Put$#FF into flag $SE71. Move flags $8E61 through $8E67 to $8E69 through $8E70 as temporary save. MoveCV and CH into flags $8E72 and $8E73. |h |3Option B|1. Put #$40 in flag $SE61 to switch to primary page 2. |h |3Function C|1. Carriage return. If not below bottom, do CR via $9204. |h |3Option C|1. Complement display by making flag $8E63 a #$CO and $8E64 a #$00. |h |3Function D|1. Block display off. If in block mode, move flags back to $8E61-8E68. Reset block flag and CH flag to zero, CV flag to bottom. |h |3Option D|1. Display primary. Switch to page One. Check primary flag and switch to primary flag page. |h |3Function E|1. Clear HIRES page to EOL using$928D. Then, clear text page ) /cl greentitbox black 16 69 (|3Table 3.4, continued\274 Complete script of HRCG) cl showpage %%%%%%%%%%%%%%%% page 78 %%%%%%%%%%%%% false setuppage 78 evenheader /col2 {/xpos 10 store /ypos 59.7 store} store % huh align? 0 3 33.5 65 2 ( ADDRESS COMMENTS |k ) ( $902B-903F \261 |h $9040-9047 \261 |h $9048-904F \261 |h $9050-9057 \261 |h $9058-9072 \261 |h $9073-907A \261 |h $9076-9082 \261 |h $9083-908D \261 |h $908E-9095 \261 |h $90%-909E \261 |h $909F-90AD \261 |h $90AE- 90BA \261 |h $90BB-90C2 \261 |h $90C2-90C8 \261 |h $90CY-90D5 \261 |h $90D6-9103 \261 |h $9104-9124 \261 |/col2 |3Function F|1. Clear HIRES page to EOS with $927A. Then, clear text page using monitor CLEOS. |h |3Function H|1. Backspace. Go left one character if entry at $902B. If screen left, go up one line. |h |3Function I|1. Set inverse video flag by putting #$75 into $8E62. |h |3Function K|1. Set caps lock flag by putting #$00 into $8E66. |h |3Function L.|1 Set lower-case flag by putting #$80 into $8E66. Unsupported function M. Apparently a scroll diagnostic, once reached by CTRL-S, CTRL-C |h |3Function N|1. Set normal video flag byputting #$00 into 8E62. |h |3Function O|1. Set option flag by putting #$40 into $8E60. Next key will complete option command. |h |3Option O|1. Pick overstrike mode by #$00 into 8E63 and #$00 into 8E64. |h |3Function P|1. Clear HIRES page via $9270 and text page via monitor HOME. Note that an image of the HIRES screen is put on text page 1. |h |3Option P|1. Pick print mode by putting #$00 into $8E63 and $8E64. |h |3Function Q|1. Home cursor inside text window. Move upper-left values toCH and CV. Then, reset text screen via monitor VTAB. |h |3Function R|1. Reverse overlay by putting #$CO into $8E63 and #$60 into $8E64. |h |3Function S|1. Shift next character by putting #$CO into flag $8E66. |h |3Option S|1. Pick scroll mode by putting #$00 into flag $8E65. |h |3Option T|1. Set transparent mode by putting #$80 into $8E6 3 and #$60 into $8E64. |h |3Function V|1. Text window, upper left, by resetting WNOLFT and WNOTOP after check for on-screen values. Transfers vertical position to CV flag if not in block mode. |h |3FunctionW|1. Text window, lower right, by resetting WNDWIDTH and WNDBTM. after check for on-screen values. ) /cl greentitbox black 0 69 (|3Table 3.4, continued\274 Complete script of HRCG) cl showpage %%%%%%%%%%%%%%%% page 79 %%%%%%%%%%%%% false setuppage 79 oddheader /col2 {/xpos 10 store /ypos 59.7 store} store % huh align? 16 3 33.5 65 2 ( ADDRESS COMMENTS |k ) ( $9125-912A \261 |h $912B-914E \261 |h $914F-9151 \261 |h $9152-9177 \261 |h $9178-917A \261 |h $917B-9196 \261 |h $9197-91C4 \261 |h |h $91C5-91F7 \261 |h $91F5-9218 \261 |h $9219-9220 \261 |h $9221-926F \261 |/col2 |3Option W. |1Set wrap mode by putting #$FF into $8F65. |h |3Function Y.|1 Open to full text screen by putting #$00 into WNDLFT and WNDTOP and #$28 into WNDWDTH and $#18 into WNDBOTM. Save as CH and CVflags if not block mode. |h |3Option Y|1. Call user subroutine A by jumping to jump command stored at $SE08. Defaults to RTS. |h |3Function Z|1 Restore defaults. Reset all flags to #00. Set full text window. Pick default character set. Display primary page. Reset user subs to RTS. |h |3Option Z.|1 Call user subroutine B by jumping to jump command stored at $8EOB. Defaults to RTS. |h |3Begin character entry|1. Exit RTS if option flag set. Check case mode and change to upper case or reset shift flag if needed. |h |3Continue character entry|1. Calculate character location and save as $EE and $EF. Calculate screen base address location and save as $EC and $ED. This is the top dot row for any character position. The running dot row address gets held in $2A and $2B.Then, the character is saved on page One text screen. Like so\274 |h $28-29 - text screen base address $2A-2B - HIRES dot row address $EC-ED - HIRES base address $EE-EF - Character-set base address |h |3Continue character entry|1. For eight dot rows, get the character dots and inverse if needed. Get the dots already on the screen; then, AND or OR with character dots if needed. Then, return result to the screen. Next, calculate the address of the next lower dot row and repeat till all of the characters have been entered. |h |3Move cursor|1. Go one to the right unless at the extreme right of the window. If a CR is needed, go down one line unless at extreme window bottom. If at bottom, check flag for scroll or wraparound, and continue. |h |3Wraparound mode|1. Set WNDTOP to top of text window. Do a monitor VTABZ to recalculate base addresses. |h |3Scrolling mode|1. Dot line source is$2A to $2B. The destination is address ) /cl greentitbox black 16 69 (|3Table 3.4, continued\274 Complete script of HRCG) cl showpage %%%%%%%%%%%%%%%% page 80 %%%%%%%%%%%%% false setuppage 80 evenheader /text1 (|p|y |1If you are attacking a very complicated target program, chances are the original author may have had some of the very same problems you did. And, |k) store /col2 {/xpos 10 store /ypos 57 store} store 0 7 33.5 61 2 ( ADDRESS COMMENTS |k ) ( |h $9270-9279 \261 |h $927A-928C \261 |h $928D-92CA \261 |h $92CB-92DF \261 |h $92DF-92EA \261 |h $92EB-92FE \261 |h $92FF-96FE \261 |/col2 $EC-$ED. Destination is eight dots above source. Starting at the top of the screen, scroll downward, loading from ($2A) and storing at ($EC). The Y register handles CH position, stepping down from WNDWDTH downward. X register handles the position of eight rows per character. One entire dot row is entered, then another until done. After a line gets remapped, the base address of the next line is calculated, making the old source the new destination, and calculating a new source. Continues until the entire screen is mapped. The bottom line is cleared via $8E63. |h |3Clear screen|1. Set CV toWNDTOP and CH to WNDLFT and then continue via $927E. |h |3Clear to end of screen|1. From present CH and CV, clear to EOL via $9291 as often as needed to empty the screen. |h |3Clear to end of line|1. Foreight dot rows. calculate address, then remove character from screen. Inverse background if needed. Y register works from CH to WN DWDTH doing one dot row at a time. X register handles dot rows, working from top of character down. |h |3Calculate HIRES base address|1. Divide CV by two. Go into the table in $92 DF-92 EA and lookup base address value. Process this value and store in $2A and $2B. |h |3A stash of table lookup values|1 used to calculate HIRES base addresses needed by $92CB or $92CD. |h |3Apparently unused garbage.|1 |h |3Bulk file of default character set|1. Holds the dot patterns of all ASCII characters. The seven least significant bits hold the horizontal dot pattern IN REVERSE for one dot line. Eight successive bytes hold the dot pattern for one character, arranged from top to bottom. Locations $92FF-93FE hold numbers and symbols. $93FF-94FE hold upper case alphabet, and $9SFF-96FE hold lower-case alphabet. Bottom dot row is blank except for any descenders. 96 characters total. ) /cl greentitbox 0 5 text1 cf black 0 69 (|3Table 3.4, continued\274 Complete script of HRCG) cl showpage %%%%%%%%%%%%%%%% page 81 %%%%%%%%%%%%% false setuppage 81 oddheader /text1 (|z|y |1if he was smart enough, he just, possibly, may have built in some problem solving diagnostics. |h|p For instance, the Adam adventures have a "Possible" and a "Did" tracing debugger that you can access with two keystrokes. Zork includes a hook that lets you stop the action after each code module, and print out whatever you like, such as the files just accessed. Zork will also give you a complete list of rooms with just a few keystrokes. A few minor changes to Wizard and the Princess and you get a guided picture tour of all the rooms. |h Be on the lookout for any diagnostic helps that may be built into the program. Then, see just how you can tap them. |h Breakpoints are another way to tackle a program. What you do is reach into the target program at a place where you want it to stop, and insert a $00 or BRK command. When the Apple reaches this point in the program, it will stop and immediately do a software interrupt. |h What happens next is decided by which monitor ROM you have in use. If you have the old ROM, the break puts you in the monitor and displays all of the working registers. If you have the autostart ROM, the BRK command does a jump indirect to the address contained in locations $03Fo (low) and $03Fl (high). You can go from this address into the monitor, or else, directly to another snoop program that spells out what each and every pointer and indirect address is up to. |h There is one clinker in the works when you use BRK. You might need the old ROM to gain control of the program so that you can change $03FO and $03Fl, and then switch to the autostart one. A "protected" program under autostart will never let you get down into the monitor or change any locations. Use of either ROM card with a hardware change over switch often can get you out of this bind. |h A breakpoint could be used as anything from a scalpel to a cannon, depending on what you want to do and how large a hole you want to blast. |h Drawing a flowchart may help you. I don't use that method too much since it sounds like something the dino people would want you to do. |h The addressing modes that give the 6502 microprocessor its extreme power are the indirect ones. These include jump indirect, indirect indexed, and the rarely used indexed indirect. All of these are identified by an address in parentheses following the mnemonic. A lot of setting up is needed to use these locations. Most often, an address pair on page Zero has to be set up ahead of time. |h Understanding the real address used for an indirect instruction can be the key to cracking tough codes. It pays to spend lots of time being sure you know exactly where these addresses are going to and why they are doing so. |h Things really get interesting when you get involved in double and triple indirect addressing, as is common in adventure programs. The code may go to some base address, pick an address pair out of a file there, and use that address as an indirect pointer in another instruction. If the files happen to be longer than 256 bytes, then double indirect is needed, rather than a single. |h Patience and practice are essential to cracking indirect codes. If all else fails, replace the indirect op code with a BRK command. On the break, get into the monitor and check the locations used to hold the indirect address. |h |/makeblue Hooks |/makeblack are attachments you make to the program to gain partial control. You might write your own small "host" program and let it "borrow" subroutines off the target program. This is one possible way to dump files off protected disk |k) store 16 69 text1 cf showpage %%%%%%%%%%%%%%%% page 82 %%%%%%%%%%%%% false setuppage 82 evenheader /text1 (|z|y |1tracks. Once you are able to use and control key subroutines in your target program, you are well on your way to solving everything else. |h|p The tape cassette is often ignored. Yet the tape system is a very valuable tool. One "protection" scheme used involves putting a program in the same space where Apple DOS 3.3 would normally reside. A custom DOS is then put somewhere else and there is no immediate way to save the program entered under DOS 3.3, since booting the DOS 3.3 overwrites and destroys the code. |h But, the cassette doesn't care. It can save any code in any location at any time. One thing you can do is move the target code down in memory below DOS, save it to cassette, and then boot the DOS. Save this lower version on DOS and, then, add a "move" command that puts it back where it wants to sit. Cassettes are also useful in upgrading between various DOS versions. They are slow, unreliable, and unwieldy, but they just might work if all else fails. |h The single step and trace features on the old monitor are very useful on some parts of some programs, particularly if you dump them to a printer. But watch out that you don't try to trace a delay loop, such as the one that waits for a disk drive motor to come up to speed. The trace operation slows things down some 10,000 times from normal speed, so a two-second delay will take several days and miles of paper to print. Sometimes you can break into the loop, reset the counter locations, and continue. Other times, you'll have to combine single step or trace with breakpoints. |h Run the code till you hit the breakpoint, and then single step from there. Tracing to a printer is one very good way to crack indirect addresses to find the files that they work with. |h Beware of tracing parts of programs that read the screen, since tracing and displaying can interact. For instance, a clear-to-end-of-screen will hang during a trace, since trace keeps resetting the screen locations. If you are printing, be sure to defeat the screen echo during these times. |h Another custom attack method is to chip away at the target. Your goal may seem to be hopelessly buried in the middle of stuff that seems so complicated that it will take you forever to understand. If all else fails, attack the easy stuff on the outside. Do this even if the easy stuff seems to have nothing at all to do with your goal. The parts of the code that outputs characters or inputs data areusually easy to read. Continue carving away on anything that looks like it might shake loose. What this indirect attack does is reduce the size of what is left to a point where you can hack at it directly. |h A big plus for the indirect attack is that it can show you the program author's style and where his head is at. Does he use self-modifying code? How does he handle multiple choice addresses? Does he use the indirect commands effectively and gracefully? Is he using mostly branches, or mostly jumps? How elegantly or how clumsily does he handle 16-bit addresses and long files? Does he extensively use the existing monitor, DOS, and BASIC subs, or is he reinventing the wheel? How clean is his organization? Is the program designed from the ground up for an Apple, or was it obviously modified from a program originally designed to run on some inferior machine? |h Answers to these questions can simplify very much the cracking of the rest of the code, since most decent programmers tend to be consistent in how they do things. If the code seems ridiculously obscure, attack the fundamental subroutines. These subroutines are the ones that won the popularity poll (the ones with all the dots). The subs to hit first are those that will not call any other subroutines, but will go ahead and do direct and obvious things. |h Common tasks of fundamental subroutines include searching a long file for a value, calculating an address, or making a hex-to-decimal conversion.) store 0 69 text1 cf showpage %%%%%%%%%%%%%%%% page 83 %%%%%%%%%%%%% false setuppage 83 oddheader /text1 (|p|y |1Once you understand these fundamental subroutines, you do not have to go through them each time they crop up, because you know what they do. If you create meaningful names for these fundamental subroutines and they will help you a lot. Then, "ripple" this new information back on through. |h Asking for help is an obvious thing to do. There is nothing more infuriating than having an 8-year-old boy, just in from off the street, make some casual comment that completely sums up what it just took you months to find out the hard way. So discuss the target program and its attack. |h Don't only do it with "experts," but rap about it to anyone who will listen. Chances are their heads are elsewhere and might put things in a new light. |h The |/makeblue |3python force feeder|1 |/makeblack takes some special hardware, but it can be very effective. A force feeder is some hardware and software modifications that include a super-powerful bus driver, say a 74S245, or maybe three of them in parallel. When you tell it to do so, it substitutes its own code for what the computer is supposed to be working with. |h For instance, even the old monitor ROM can't help plowing part of the display page, the first few keybuffer locations, and part of page Zero when it is activated. A sneaky programmer can hide things in plowable locations. But not so with a force feeder. Besides being able to force a monitor reset any time you like, a force feeder can substitute anything at any place in the program. It can also move copies of plowable locations to unplowable ones for analysis. |h As a much simpler example of force feeding, consider the "top display line" copy protection hoax. What you do is switch to HIRES and, then, put a key jump or some other "magic" code that you want "hidden" on the top line of text display page One, starting at location $0400. This code is called early in the program and the program bombs if the code is not there. Naturally, the code gets erased immediately after use. |h This, in theory, makes any messing with the program impossible. Any tampering at all will scroll up the display page and destroy the magic code. Sounds both bulletproof and infuriating. In reality, this is only a "seven-second" copy protection. What you do is force feed the Apple by making it display only text page One, and this "hidden" code actually leaps out at you, shouting to be heard. To force feed the page One display on older Apples, remove integrated circuit F14 and ground pin l\o. 6 of the socket at Fl4. The hidden bytes will appear in Apple video-screen code, rather than op code, but if you got this far, that just adds to the fun. Similar force feeding games can be played with most of the Apple soft switches that are needed for analysis or degbug. |h Another handy debug trick is the partial boot. Instead of letting the target program completely boot, you only let it go so far and, then, analyze what you have. This catches code modules before they are moved to cover DOS, and so on. For instance, the program, |/makeblue Pool 1.5|/makeblack , is generally considered to have excep­ tionally good, or "three-hour," copy protection. But, use a partial boot and the "three-hour" protection drops down to a much more convenient "eighteen­ minute" protection. |h More elegant boot tracing can also be done. The trick here is to carefully watch the disk drive with the cover off and time the different parts of the loading and protecting process. By the way, there's one sure-fire way to read any disk at any time. Just glomp a logic analyzer with a 6502 personality module in it, onto the CPU and you are home free. Unfortunately, you can buy a dozen Apples for the price of one better grade logic analyzer, so this ultimate weapon does not see much use. |h Change detection is yet another attack method. However, I have not fully explored this one. What you do is dump part of memory, run a portion of |k ) store 16 69 text1 cf showpage %%%%%%%%%%%%%%%% page 84 %%%%%%%%%%%%% false setuppage 84 evenheader /text1 (|z|y |1the target program, and then see what changed. By finding out how, when, and why that change took place, you can often gain all sorts of insight into what is going on. |h|p Some day, I would like to build the ultimate change detector. This would take a DMA modification to the Apple that would let a second Apple or some type of dedicated hardware give you an instant and separate picture of memory activity while the main program was running. One display would show what the program was doing, while the second would show you each and every memory location of interest. Ideally, such a program should present any location or any block of locations that you want and would clearly identify them. By using this ultimate change detector, you could actually watch the program while it was doing its thing. |h A variable-speed feature would also be nice here, so you could slow down or stop key activities without waiting forever for them to get through a delay loop. |h We've already seen how altering files can tell you lots of things in a hurry about your program. Sometimes you are shooting in the dark since some file locations may only rarely be used or might be used only in an obscure way. File changing is certainly worth a try. |h If you are going to change the target program or interact with it, it might pay to put the program on your own assembler and create your own source code. This lets you add your own hooks and make changes of your own choosing inside the target program. The EDASM on the DOS Toolkit is ideal for this. Assembling your own source code backwards from the object program is quite a hassle, though, and you shouldn't try it unless you have pretty much cracked everything else. Disassembler programs, such as RAK-WARE's |/makeblue DISASM|/makeblack , are also available that will "capture" code for your favorite assembler. |h Sitting on your program is often overlooked. Just walk away from the attack for hours or days, and things that should have been obvious all along will leap out at you. Let your subconscious work on the puzzles that are holding you up. |h Another thing that can help is to try attacking a similar program, either by the same author or by another that does the same thing in a simpler or easier to understand way. The insights you get from one program will help you attack the other program. |h Deciphering special codes may be needed in longer adventures. These codes are more often used to make code more compact than they are to purposely "hide" the meanings of what they hold. The trouble is that most compaction schemes also do a most thorough job of masking everything the file holds. |h For instance, in |/makeblue Zork|/makeblack , the ASCII strings are compacted so that two bytes hold three characters. Some newer adventures use paired letter or similar codes to remove the redundancy from text messages so that long text files will fit inside the machine. This is how the Collossial Cave adventure from Adventure International manages to get everything that once demanded a mainframe dino into a 48K Apple without needing repeated disk access. |h About the only way to attack these codes is to go into the code modules that decipher them. Then, decipher the decipheree. Single step, trace, or breakpoint access code modules till they show you how to read the file. Usually, there will be some obscure command or program feature that will do things a lot faster or simpler than the others. Trace this command or feature out and let it crack the code for you. The last resort, of course, is to give up. Go back and attack something that is simpler. |h My first machine language attack of a big program was Adam's |/makeblue Pyramid |k) store 0 69 text1 cf showpage %%%%%%%%%%%%%%%% page 85 %%%%%%%%%%%%% false setuppage 85 oddheader 16 63.3 (CONVERGE ON YOUR GOAL) burpleheader 16 27 (WRITE IT DOWN!) burpleheader /adjl {-9 0 translate} store 22 34 21 13 (|7|h|/adjl The HRCG scroll hook is at $9214. |h $9215 holds the address low of the scroll subroutine. |h $9216 holds the address high of the scroll subroutine. |h The existing scroll routine starts at $9221 and ends with $926F. ) /cl orangebox /text1 (|z|y |1|/makeblue of Doom. |/makeblack |1This was done on a wilderness firetower using nothing but a 6502 pocket card. It literally took all summer, but it led to this attack method, and there is no better way to learn machine language programming.) store /text2 (|p|y |1Just as soon as you have the structure pretty well defined and as soon as you have cracked most of the code modules, return to your original goal and solve that particular problem. |h Our goal in HRCG was to find the scroll hooks. By now, they should leap out at you. Just as the cursor is about to go off screen at $9208, a check is made to see whether scrolling or wraparound is to be used. If scrolling is active, $9213 does a jump to the scroll subroutine starting at $9221. Specifically, $9214 will hold the low address and $9215 will hold the high address of the scrolling subroutine. |h Just change these hooks enough so that you can use your own scrolling routine. Try it!) store /text3 (|p|y |1Easy, wasn't it? If not, go through a few practice target programs and see how fast and powerful the tearing method can be.) store /text4 (|p|y |1Surely you don't want to go through all this a second time on the same target program. So, carefully write down everything you learned in some form that works for you. |h Make a clean copy of your analysis on the second listing you made. Also, make a neat new table of variables, a new cross-reference, and write a complete new script. Put most of this information onto disk so that you can have printable and updateable copies for later use. Use your word processor. |h The insight that you have now will be long forgotten in a month. Be sure that you will be able to later recover what you already have done, and will be able to do so both quickly and hassle free. |h Resist the urge to pull a |/makeblue |3"EUREKA! I have found it!"|1|/makeblack and run off with only your limited goal met. Do so, and the key information will disappear down the tube somewhere and all will be lost. |h The following outline sums up all the steps involved in tearing into machine language code. Go back over them, and you'll find three parts to the attack. First you |/makeblue |3 prepare|1|/makeblack yourself, then you |/makeblue |3attack|1|/makeblack the target program, letting it reveal itself through its form and structure. Finally, you |/makeblack |1follow up|1|/makeblack the attack to reach your goal. ) store 16 69.5 text1 cf 16 61.3 text2 cf 16 32 text3 cf 16 24.5 text4 cf showpage %%%%%%%%%%%%%%%% page 86 %%%%%%%%%%%%% false setuppage 86 evenheader 10 32 22 36 3.3 (TEARING INTO MACHINE\nLANGUAGE CODE) (|/font1 |/makedkblue |7PREPARATION |h|/black |1 ( ) Assemble the toolkit. ( ) Grok the program. ( ) Go to the horse's whatever. ( ) Set a limited goal. ( ) Empty the machine. ( ) Find where the program sits. ( ) List and hex dump the program. |h |/makedkblue |3ATTACK |h|/black |1 ( ) Separate action from bulk files. ( ) Paint subroutine returns green. ( ) Paint subroutine calls orange. ( ) Paint absolute jumps pink. ( ) Paint relative branches blue. ( ) Separate modules and stashes. ( ) Identify files and stashes. ( ) Attack variables and constants. ( ) Paint housekeeping yellow. |h |/makedkblue |3FOLLOW UP |h|/black |1( ) Make a list of variables. ( ) Write a script. ( ) Customize the attack. ( ) Converge on your goal. ) /cl bluetitbox /text1 (|p|y |1Here is a quick summary of the tearing method\274) store /text2 (|p|y |1Practice makes perfect. Try it. |h An obvious second program for your tearing attack would be FID on the DOS System master diskette. Try this one on your own and see how far you get. As a specific goal, find out how to use the code that tells you how much space you have left on a diskette.) store 0 69 text1 cf 0 30 text2 cf showpage %%%%%%%%%%%%%%%% page 87 %%%%%%%%%%%%% false setuppage 87 oddheader /setpurple { 74 setwebtint } store /adjtxtwide {/txtwide 40 store} store /tabin {7 0 translate} store /tabout {-7 0 translate} store /tabs [ 12] store 8 2.5 43 65.5 2 (|3WILL THE REAL LISTING PLEASE JUMP OUT?) (|/adjtxtwide |y|p |1There will be times when the disassembler in the Apple monitor lies like a rug. |h|p |1A disassembler always assumes it is working with valid op codes. It starts witth the first code byte it finds and, then, decides what operation the Apple is to to. Depening on the particular op code, one, two, or three byte, will be needed to complete the operation. |h For instance, the CLC or clear command is an implied addressing instruction handled with a single byte. No further information is needed. The LDX #05 immediate command takes two bvtes, one to tell you what lo do and one to answer "how much?" The STA $4050 command uses absolute addressing and takes three bytes, one to tell us what to do and two bytes to answer "Where?" by giving us address low and, then, address high values. |h Thus, a disassembler will automatically jump one, two, or three bytes to get to the start of the new instruction. |3|/makeblue The disassembler always assumes that it is working with |/makeblue valid code from a legal starting point|1|/makeblack . |h If either the starting point is wrong or if what is being disassembled is not legal, the lister starts lying. |h Suppose we have these bytes stashed in memory\274 |h|/setpurple |/makeburple |9|/tabin $0800- 80 8D AD 02 A5 18 EA |h|/tabout |/makeblack |1Here is what you get if you try to disassemble this code from various starting points\274 |h|/tabin |/setpurple |/makeburple |9$0800- 80 |t??? $0801- 80 AD 02 |tSTA $02AD $0804- A5 18 |tSTA $18 $0806- EA |tNOP |h $0801- 80 AD 02 |tSTA $02AD $0804- AS 18 |tSTA $18 $0806- EA |tNOP |h $0802- AD 02 A5 |tLDA $A502 $0805- 18 |tCLC $0806- EA |tNOP |h $0803- 02 |t??? $0804- AS 18 |tSTA#18 $0806- EA |tNOP |h|/tabout |/black |1|/makeblack We see that we get a different disassemblv every time, depending on where we start from. Which one is correct? |h The correct disassembly is the one that begins with the first valid op code on tbe list. The first valid op code is often pointed to elsewhere in the program bv a jump branch. call, or an external entry point. |h You can expect the "lister" to lie' about one-half of the time when it comes out of a file or dead code and starts into legal code. |h Usuallv the "lister" will correct itself after two or three wrong entries. So, you usually have to worry about the first few entries into valid code. |h If what you have just listed seems dumb, try listing from one above or one below where you think the legal code starts. Most of the time, there will only be one rational place anci the valid code will leap out at you. But remember that the "lister" will only tell the truth when both true code and a true starting point to work with. ) /cf bluetitbox showpage %%%%%%%%%%%%%%%% page 88 %%%%%%%%%%%%% false setuppage 88 evenheader /adjtxtwide {/txtwide 15 store} store 13 35 18 17 2 (SEEDS AND STEMS) ( |/adjtxtwide |y |1To extend the life of any game paddle connector that gets used a lot, plug your paddles into a 16 pin, premium machined contact DIP socket. Then plug this socket into J14 on the Apple. |h It pays to put sockets on all your joysticks, paddles, and whatever, as well. Should any pin bend or break, repairs are far easier.) /cf bluetitbox 13 13 18 17 2 (SEEDS AND STEMS) ( |/adjtxtwide |y |1To edit a comment line in EDASM without having holes chopped in it, you can use the "T" command to eliminate all tabbing. |h To restore EDASM to normal, you can either reboot, or else, use "Tl 4, 19, 29" commands. |h All of your tabs must be restored before assembly.) /cf bluetitbox showpage % EOF