home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Brotikasten
/
BROTCD01.iso
/
c128
/
c154.d64
/
lrr.doc
< prev
next >
Wrap
Text File
|
1995-08-09
|
67KB
|
1,809 lines
=============================================================================
╠╔╘╘╠┼ ╥┼─ ╥┼┴─┼╥: ═╙-─╧╙ FILE READER FOR THE 128 AND 1571/81 DRIVES.
BY ├RAIG ┬RUCE <CSBRUCE@NEUMANN.UWATERLOO.CA>
1. ╔╬╘╥╧─╒├╘╔╧╬
╘HIS ARTICLE PRESENTS A PROGRAM THAT READS ═╙-─╧╙ FILES AND THE ROOT DIRECTORY
OF ═╙-─╧╙ DISKS. ╘HE PROGRAM COPIES ONLY FROM DRIVE TO DRIVE WITHOUT
BUFFERING FILE DATA INTERNALLY. ╘HIS IS SIMPLER AND IMPOSES NO LIMITS ON THE
SIZE OF THE FILES TRANSFERRED, ALTHOUGH IT REQUIRES THE USE OF TWO DISK DRIVES
(OR A LOGICAL DRIVE). ╘HE USER-INTERFACE CODE IS WRITTEN IN ┬┴╙╔├ AND
PRESENTS A FULL-SCREEN FILE SELECTION MENU. ╘HE GRUNT-WORK CODE IS WRITTEN IN
ASSEMBLY LANGUAGE AND OPERATES AT MAXIMUM VELOSITY.
╘HE ┬URST ├OMMAND ╔NSTRUCTION ╙ET OF THE 1571/81 IS USED TO READ THE ═╙-─╧╙
DISK BLOCKS AND THE STANDARD KERNEL ROUTINES ARE USED FOR OUTPUTTING THE
DATA. (╔ AM AN OPERATING SYSTEMS SPECIALIST, SO ╔ CALL IT A KERN┼L!) ╘HUS,
THE ═╙-─╧╙ FILES MUST BE READ FROM A 1571 OR 1581 DISK DRIVE, BUT THE OUTPUT
DEVICE MAY BE ANY DISK DRIVE TYPE, THE SCREEN OR A PRINTER, OR A VIRTUAL DRIVE
TYPE SUCH AS ╥┴═╠INK, ╥┴═─RIVE, OR ╥┴═─╧╙ (FOR THE ╥┼╒). ╔T IS INTERESTING TO
NOTE THAT THE DATA CAN BE READ IN FROM AN ═╙-─╧╙ DISK FASTER THAN IT CAN BE
WRITTEN OUT TO A 1571, 1581, OR EVEN A ╥┴═─╧╙ FILE. ┴ ╥┴═╠INK CAN SWALLOW THE
DATA ONLY SLIGHTLY FASTER THAN IT CAN BE READ.
╠ITTLE ╥ED ╥EADER (╠╥╥) SUPPORTS DOUBLE DENSITY 3.5" DISKS FORMATTED WITH 80
TRACKS, 9 SECTORS PER TRACK, AND 2 SIDES WITH A 1581 AND 5.25" DOUBLE DENSITY
DISKS FORMATTED WITH 40 TRACKS, 9 SECTORS PER TRACK, AND 2 SIDES WITH A 1571.
┴ LIMIT OF 128 DIRECTORY ENTRIES AND 3 ╞ILE ┴LLOCATION ╘ABLE (╞┴╘) SECTORS IS
IMPOSED. ╘HERE MUST BE 2 COPIES OF THE ╞┴╘ AND THE CLUSTER SIZE MAY BE 1 OR 2
SECTORS. ╘HE SECTOR SIZE MUST BE 512 BYTES.
╧H, ABOUT THE NAME. ╔T IS A PLAY ON THE NAME OF ANOTHER ═╙-─╧╙ FILE COPIER
AVAILABLE FOR THE ├-128. "╠ITTLE" MEANS THAT IT IS SMALLER IN SCOPE THAN THE
OTHER PROGRAM, AND "╥ED" IS A DIFFERENT PRIMARY COLOR TO AVOID ANY LEGAL
COMPLICATIONS. ╔T IS ALSO THE NON-WHITE COLOR OF THE FLAG OF THE COUNTRY OF
ORIGIN OF THIS PROGRAM (NO, ╔ AM NOT ╩APANESE). ┴LSO, THIS PROGRAM IS ╨UBLIC
─OMAIN ╙OFTWARE, AS IS ALL SOFTWARE ╔ DEVELOP FOR 8-BIT ├OMMODORE ├OMPUTERS.
╞EEL FREE TO ┼-MAIL ME IF YOU HAVE QUESTIONS OR COMMENTS ABOUT THIS ARTICLE.
2. ╒╙┼╥ ╟╒╔─┼
╠╧┴─ AND ╥╒╬ THE "LRR.128" ┬┴╙╔├ PROGRAM FILE. ╫HEN THE PROGRAM IS FIRST RUN,
IT WILL DISPLAY AN "INITIALIZING" MESSAGE AND WILL LOAD IN THE BINARY MACHINE
LANGUAGE PACKAGE FROM THE "CURRENT" ├OMMODORE ─╧╙ DRIVE (THE CURRENT DRIVE IS
OBTAINED FROM ╨┼┼╦(186) - THE LAST DEVICE ACCESSED). ╘HE BINARY PACKAGE IS
LOADED ONLY ON THE FIRST RUN AND IS NOT RELOADED ON SUBSEQUENT RUNS IF THE
PACKAGE ╔─ FIELD IS IN PLACE.
2.1. ═┴╔╬ ╙├╥┼┼╬
╘HE MAIN SCREEN OF THE PROGRAM IS THEN DISPLAYED. ╘HE MAIN SCREEN OF THE
PROGRAM WILL LOOK SOMETHING LIKE THIS:
═╙-─┼╓=9 ═╙-╘┘╨┼=1581 ├┬═-─┼╓=8
╬╒═ ╙ ╘╥╬ ╘┘╨ ╞╔╠┼╬┴═┼ ┼╪╘ ╠┼╬╟╘╚
--- - --- --- -------- --- ------
1 * ┴╙├ ╙┼╤ ╚┴├╦4 ╘╪╘ 120732
2 ┬╔╬ ╨╥╟ ╥┴═─╧╙ ╙╞╪ 34923
─=─╔╥┼├╘╧╥┘ ═=═╙-─┼╓ ╞=├┬═-─┼╓ ╤=╤╒╔╘
╘=╘╧╟╟╠┼-├╧╠╒═╬, ├=├╧╨┘-╞╔╠┼╙, +/- ╨┴╟┼
EXCEPT THAT IMMEDIATELY AFTER STARTING UP, "<NO FILES>" WILL BE DISPLAYED
RATHER THAN FILENAMES. ╘HE "═╙-─┼╓" AND "═╙-╘┘╨┼" FIELDS GIVE THE DEVICE
NUMBER AND TYPE OF THE DRIVE CONTAINING THE ═╙-─╧╙ DISK TO COPY FROM, AND THE
"├┬═-─┼╓" GIVES THE DEVICE NUMBER OF THE DRIVE/VIRTUAL DRIVE/CHARACTER DEVICE
TO COPY FILE DATA TO.
╔NFORMATION ABOUT ALL ═╙-─╧╙ FILES IN THE ROOT DIRECTORY OF THE ═╙-─╧╙ DISK IS
DISPLAYED IN COLUMNS BELOW THE DRIVE INFORMATION. "╬╒═" GIVES THE NUMBER OF
THE ═╙-─╧╙ FILE IN THE DIRECTORY LISTING, AND "╙" INDICATES WHETHER THE FILE
IS "SELECTED" OR NOT. ╔F THE FILE IS SELECTED, AN ASTERISK (*) IS DISPLAYED;
OTHERWISE, A BLANK IS DISPLAYED. ╫HEN YOU LATER ENTER ├OPY ═ODE, ONLY THE
FILES THAT HAVE BEEN "SELECTED" ARE COPIED.
╘HE "╘╥╬" FIELD INDICATES THE CHARACTER TRANSLATION SCHEME TO BE USED WHEN THE
FILE IS COPIED. ┴ VALUE OF "┬╔╬" (BINARY) MEANS NO TRANSLATION AND A VALUE OF
"┴╙├" (ASCII) MEANS THE FILE CHARACTERS ARE TO BE TRANSLATED FROM ═╙-─╧╙ ┴╙├╔╔
(OR "┴╙├╔╔-├R╠F") TO ╨┼╘╙├╔╔. ╘HE "╘┘╨" FIELD INDICATES THE TYPE OF
├OMMODORE-─╧╙ FILE TO CREATE FOR WRITING THE ═╙-─╧╙ FILE CONTENTS INTO. ╘HE
POSSIBLE VALUES ARE "╙┼╤" (SEQUENTIAL) AND "╨╥╟" (PROGRAM). ╘HE VALUES OF THE
╘╥╬ AND ╘┘╨ FILEDS ARE SET INDEPENDENTLY, SO YOU CAN COPY BINARY DATA TO ╙┼╤
FILES AND ASCII DATA TO ╨╥╟ FILES IF YOU WISH.
╘HE "╞╔╠┼╬┴═┼" AND "┼╪╘" FIELDS GIVE THE FILENAME AND EXTENSION TYPE OF THE
═╙-─╧╙ FILES AND "╠┼╬╟╘╚" GIVES THE EXACT LENGTH OF THE FILES IN BYTES. ╬OTE
THAT IF YOU PERFORM "┴╙├" TRANSLATION ON A FILE, ITS ╨┼╘╙├╔╔ VERSION WILL HAVE
A SHORTER LENGTH.
2.2. ╒╙┼╥ ├╧══┴╬─╙
╘HE BOTTOM OF THE SCREEN GIVES THE COMMAND SUMMARY. ┴FTER STARTING THE
PROGRAM, YOU WILL WANT TO SETUP THE ═╙-─╧╙ AND ├┬═-─╧╙ DRIVES WITH THE "═" AND
"╞" COMMANDS. ╙IMPLY PRESS THE (LETTER) KEY CORRESPONDING TO THE COMMAND
NAME TO ACTIVATE THE COMMAND. ╨RESSING ═ WILL PROMPT YOU FOR THE ═╙-─╧╙ ─RIVE
╬UMBER AND THE ═╙-─╧╙ ─RIVE ╘YPE. ╔N BOTH CASES, TYPE THE NUMBER AND PRESS
╥┼╘╒╥╬. (╙ORRY FOR INSULTING ALL NON-NOVICES OUT THERE, BUT ╔ WANT TO BE
COMPLETE). ╘HE ═╙-─╧╙ DRIVE NUMBER CANNOT BE THE SAME AS THE ├┬═-─╧╙ DRIVE
NUMBER (SINCE THE PROGRAM COPIES FROM DRIVE-TO-DRIVE WITHOUT INTERNAL
BUFFERING). ╞OR THE DRIVE TYPE, ENTER AN "8", "81", OR "1581" FOR A 1581
DRIVE OR ANYTHING ELSE FOR A 1571 DRIVE.
╨RESSING ╞ WILL PROMPT YOU FOR THE ├┬═-─╧╙ DEVICE NUMBER. ┘OU MAY ENTER A
NUMBER FROM 0 TO 30, EXCEPT THAT IT MUST NOT BE THE ═╙-─╧╙ DRIVE NUMBER.
┼NTER A "1" FOR ├ASSETTE ─RIVE (╟OD FORBID!), A "3" FOR THE SCREEN, A "4" FOR
THE PRINTER (WITH AN AUTOMATIC SECONDARY ADDRESS OF 7 (LOWERCASE)), ANY NUMBER
ABOVE 7 FOR A ├OMMODORE DISK DRIVE OR SPECIAL VIRTUAL DRIVE, OR A VALUE OF "0"
FOR THE SPECIAL "NULL" DRIVE. ┴ ├┬═-─┼╓ VALUE OF 0 WILL CASE THE PROGRAM TO
READ ═╙-─╧╙ FILES AND DO NOTHING WITH THE OUTPUT. ┘OU CAN USE THIS FEATURE TO
CHECK OUT THE RAW READING SPEED OF THE PROGRAM.
┴FTER SETTING UP THE DRIVES, PRESS ─ TO READ IN THE ROOT DIRECTORY OFF THE
═╙-─╧╙ DISK. ╘HE DATA WILL COME BLAZING IN FROM THE DISK BUT ┬┴╙╔├ WILL TAKE
ITS GOOD OLE TIME SIFTING THROUGH IT. ╞ILENAMES ARE DISPLAYED ON THE SCREEN
AS THEY ARE SCANNED IN. ╘HE PROGRAM WILL (EVENTUALLY) RETURN TO THE MAIN
SCREEN AND DISPLAY THE FORMATTED FILE INFORMATION. ╧NE NOTE: THE PROCESS OF
LOGGING IN A 1581 ═╙-─╧╙ DISK TAKES ABOUT 12 SECONDS (ON MY 1581, ANYWAY), SO
BE PATIENT. ┴N ═╙-─╧╙ DISK WILL HAVE TO BE "LOGGED IN" EVERY TIME YOU CHANGE
═╙-─╧╙ DISKS. (─ISKS ARE LOGGED IN AUTOMATICALLY).
┴ COUPLE OF NOTES ABOUT ACCESSING ═╙-─╧╙ DISKS: DON'T TRY TO ACCESS A DEVICE
THAT IS NOT PRESENT BECAUSE THE MACHINE LANGUAGE ROUTINES CANNOT HANDLE THIS
ERROR FOR SOME REASON AND WILL LOCK UP, REQUIRING A ╙╘╧╨+╥┼╙╘╧╥┼. ┴LSO, MAKE
SURE THAT AN ACTUAL ═╙-─╧╙ DISK IS LOADED INTO THE DRIVE. ╔F YOU ACCIDENTALLY
PLACE ├OMMODORE-─╧╙ DISK INTO THE ═╙-─╧╙ DRIVE, THE 1581 WILL REPORT AN
INVALID BOOT PARAMETERS ERROR (#60), BUT A 1571 WILL LOCK UP (SINCE ╔ DON'T
CHECK THE SECTOR SIZE AND MY BURST ROUTINES ARE EXPECTING 512 BYTES TO COME
OUT OF A SECTOR WHEREAS ├OMMODORE DISKS HAVE ONLY 256 BYTES PER SECTOR).
╬OW YOU ARE READY TO PICK WHAT FILES YOU WANT COPIED AND HOW YOU WANT THEM
COPIED. ┘OU WILL NOTICE THAT A "CURSOR" APPEARS IN THE "╙" COLUMN OF THE
FIRST FILE. ┘OU MAY MOVE THE CURSOR AROUND WITH THE CURSOR KEYS: ╒╨, ─╧╫╬,
╠┼╞╘, ╥╔╟╚╘, ╚╧═┼, AND ├╠╥. ├╠╥ (╙╚╔╞╘-╚╧═┼) WILL MOVE THE CURSOR BACK TO THE
FIRST FILE ON THE FIRST SCREEN. ┘OU CAN MOVE THE CURSOR AMONG THE SELECT,
TRANSLATION, AND FILE-TYPE COLUMNS OF ALL THE FILES. ╨RESSING A ╙╨┴├┼ OR A
╥┼╘╒╥╬ WILL TOGGLE THE VALUE OF THE FIELD THAT THE CURSOR IS ON. ╘O TOGGLE
ALL OF THE VALUES OF THE "CURSOR" COLUMN (INCLUDING FILES ON ALL OTHER
SCREENS), PRESS ╘. ┘OU WILL NOTICE THAT MOVING THE CURSOR AROUND AND TOGGLING
FIELDS IS A BIT SLUGGISH, ESPECIALLY IF YOU ARE IN ╙LOW MODE ON THE 40-COLUMN
SCREEN. ─ID ╔ MENTION THAT THIS PROGRAM WILL RUN ON EITHER THE 40 OR
80-COLUMN SCREEN? ╘OGGLING AN ENTIRE COLUMN CAN TAKE A COUPLE OF SECONDS.
╔F THERE ARE MORE THAN 18 ═╙-─╧╙ FILES, YOU CAN PRESS THE "+" AND "-" KEYS TO
MOVE AMONG ALL OF THE SCREENS OF FILES. ╘HE CURSOR MOVEMENT KEYS WILL WRAP
AROUND ON THE CURRENT SCREEN. "+" IS PAGE FORWARD, AND "-" IS PAGE BACKWARD.
╘HE SCREENS WRAP AROUND TOO.
┴FTER YOU HAVE SELECTED ALL OF THE FILES YOU WANT TO COPY AND THEIR TRANSLATION
AND FILE-TYPE FIELDS HAVE BEEN SET, PRESS THE ├ KEY TO GO INTO ├OPY ═ODE (NEXT
SECTION). ┴FTER COPYING, YOU ARE RETURNED TO THE MAIN SCREEN WITH ALL OF THE
FIELD SETTINGS STILL INTACT. ╘O EXIT FROM THE PROGRAM, PRESS ╤.
2.3. ├╧╨┘ ═╧─┼
╫HEN YOU ENTER COPY MODE, THE SCREEN WILL CLEAR AND THE NAME OF EACH SELECTED
FILE IS DISPLAYED AS IT IS BEING COPIED. ╔F AN ERROR IS ENCOUNTERED ON EITHER
THE ═╙-─╧╙ OR ├┬═-─╧╙ DRIVE DURING COPYING, AN ERROR MESSAGE WILL BE DISPLAYED
AND COPYING WILL CONTINUE (AFTER YOU PRESS A KEY FOR ═╙-─╧╙ ERRORS).
╘O GENERATE A ├┬═-─╧╙ FILENAME FROM AN ═╙-─╧╙ FILENAME, THE EIGHT FILENAME
CHARACTERS ARE TAKEN (INCLUDING SPACES) AND A DOT (.) AND THE THREE CHARACTERS
OF THE EXTENSION ARE APPENDED. ╘HEN, ALL SPACES ARE REMOVED, AND IF THE NAME
ENDS WITH A DOT (.) CHARACTER, THEN THAT DOT CHARACTER IS REMOVED AS WELL. ╔
THINK THIS IS FAIRLY REASONABLE.
╔F THERE ALREADY IS A FILE WITH THE SAME FILENAME ON THE ├┬═-─╧╙ DISK, THEN
YOU WILL BE PROMPTED IF YOU WANT TO OVERWRITE THE FILE OR NOT. ┼NTERING AN
"N" WILL ABORT THE COPYING OF THAT FILE AND GO ON TO THE NEXT FILE, AND
ENTERING A "Y" (OR ANYTHING ELSE) WILL CAUSE THE ├┬═-─╧╙ FILE TO BE
"SCRATCHED" AND THEN RE-WRITTEN.
╘HE PHYSICAL COPYING OF THE FILE IS DONE COMPLETELY IN MACHINE LANGUAGE AND
NOTHING IS DISPLAYED ON THE SCREEN WHILE THIS IS HAPPENING, BUT YOU CAN FOLLOW
THINGS BY LOOKING AT DAS BLINKIN LICHTES AND LISTENING FOR CLICKS AND GRINDS.
┘OU WILL PROBABLY BE SURPRISED BY THE ═╙-─╧╙ FILE READING SPEED (╔ MEAN IN A
GOOD WAY). ╘HE DISK DATA IS READ IN WHOLE TRACKS AND CACHED IN MEMORY AND THE
DIRECTORY INFORMATION AND THE ╞┴╘ ARE RETAINED IN MEMORY AS WELL. ╘HE RESULT
IS THAT MINIMAL TIME IS SPENT READING DISK DATA, AND NO COSTLY SEEKS ARE
REQUIRED FOR OPENING A NEW ═╙-─╧╙ FILE. ┴ RESULT IS THAT SMALL FILES ARE
COPIED ONE AFTER ANOTHER VERY QUICKLY. ┘OU WILL HAVE TO WAIT, HOWEVER, ON THE
RELATIVELY SLOW STANDARD KERNEL/├OMMODORE-─╧╙ FILE WRITING.
┴ FEW CHANGES HAD TO BE MADE TO THE PROGRAM TO ACCOMODATE THE ╥┴═─╧╙ PROGRAM.
╥┴═─╧╙ USES MEMORY FROM $2300 TO $3╞╞╞ OF ╥┴═0, WHICH IS NOT REALLY A GOOD
PLACE FOR A DEVICE DRIVER, AND IT USES SOME OF THE ZERO-PAGE LOCATIONS THAT ╔
WANTED TO USE. ┬UT, DIFFICULTIES WERE OVERCOME. ╘HE IMPORTANCE OF ╥┴═─╧╙
COMPATIBILITY IS THAT IF YOU ONLY HAVE ONE DISK DRIVE BUT YOU HAVE AN ╥┼╒, YOU
CAN USE ╥┴═─╧╙ TO STORE THE ═╙-─╧╙ FILES TEMPORARILY. ╔F YOU ONLY HAVE ONE
DISK DRIVE AND NO ╥┼╒, YOU ARE ╙╧╠ (╧UT OF ╠UCK) UNLESS YOU CAN GET A
╥AM─ISK-TYPE PROGRAM FOR AN UNEXPANDED 128. ╘HE ╥┴═─╧╙ PROGRAM IS AVAILABLE
FROM ╞╘╨ SITE "CCOSUN.CALTECH.EDU" IN FILE "/PUB/RKNOP/UTIL128/RAMDOSII.SFX".
╧NE NOTE ╔ FOUND OUT ABOUT ╥┴═─╧╙: YOU CANNOT USE A
─╧╨┼╬#1,(├╞$),╒(├─),╫
WITH IT LIKE YOU ARE SUPPOSED TO BE ABLE TO; YOU HAVE TO USE A
─╧╨┼╬#1,(├╞$+",╫"),╒(├─)
╚ERE IS A TABLE OF COPYING SPEEDS FOR COPYING FROM 1571S AND 1581S WITH ┴╙├
AND ┬╔╬ TRANSLATION MODES. ┴LL FIGURES ARE IN BYTES/SECOND. ╘HESE RESULTS
WERE OBTAINED FROM COPYING A 127,280 BYTE TEXT FILE (THE TEXT OF ├= ╚ACKING
╔SSUE #3).
╞╥╧═ \ ╘╧: "NULL" ╥┴═╠INK ╥┴═─╧╙ ╩─1581 ╩─1571
-------+ ------ ------- ------ ------ ------
81-BIN ▄ 5772 3441 2146 N/A 644
81-ASC ▄ 5772 3434 2164 N/A 661
71-BIN ▄ 4323 2991 1949 1821 N/A
71-ASC ▄ 4323 2982 1962 1847 N/A
╘HE "NULL" DEVICE IS THAT "0" ├┬═-─╧╙ DEVICE NUMBER, AND A COUPLE OF ENTRIES
ARE "N/A" SINCE ╔ ONLY HAVE ONE 1571 AND ONE 1581. ╬OTE THAT MY 71 AND 81 ARE
╩IFFY─╧╙-IFIED, SO THE PERFORMANCE OF A STOCK 71/81 WILL BE POORER. ╩IFFY─╧╙
GIVES ABOUT A 2X PERFORMANCE IMPROVEMENT FOR THE STANDARD FILE ACCESSING CALLS
(OPEN, CLOSE, CHRIN, CHROUT). ╥┴═─╧╙ DOESN'T SEEM TO BE AS SNAPPY AS YOU
MIGHT THINK.
╘HE "NULL" FIGURES ARE QUITE IMPRESSIVE, BUT THE RAW SECTOR READING SPEED
WITHOUT THE OVERHEAD OF MUCKING AROUND WITH FILE ORGANIZATION IS 6700
BYTES/SEC FOR A 1581 AND 4600 ┬/S FOR A 71. ╘HE REASON THAT THE 1571 OPERATES
SO QUICKLY IS THAT ╔ USE A SECTOR INTERLEAVE OF 4 (WHICH IS OPTIMAL) FOR
READING THE TRACKS. ╔ THINK THAT OTHER ═╙-─╧╙ FILE COPIER PROGRAM USES AN
INTERLEAVE OF 1 (WHICH IS NOT OPTIMAL). ╔ LOSE SOME OF THE RAW PERFORMANCE
BECAUSE ╔ COPY THE FILE DATA INTERNALLY ONCE BEFORE OUTPUTTING IT (TO SIMPLIFY
SOME OF THE CODE).
╔N A COUPLE OF PLACES YOU WILL NOTICE THAT ┴╙├ TRANSLATION GIVES SLIGHTLY
BETTER OR SLIGHTLY WORSE PERFORMANCE THAN ┬╔╬. ╘HIS IS BECAUSE ALTHOUGH
SLIGHTLY MORE WORK IS REQUIRED TO TRANSLATE THE CHARACTERS, SLIGHTLY FEWER
CHARACTERS WILL HAVE TO BE WRITTEN TO THE ├┬═-─╧╙ FILE, SINCE ╨┼╘╙├╔╔ USES
ONLY ├╥ WHERE ═╙-─╧╙ ┴╙├╔╔ USES ├╥ AND ╠╞ TO REPRESENT END-OF-LINE.
╘RANSLATION IS DONE BY USING A TABLE (THAT YOU CAN CHANGE IF YOU WISH). ═ANY
ENTRIES IN THIS TABLE CONTAIN A VALUE OF ZERO, WHICH MEANS THAT NO CHARACTER
WILL BE OUTPUT ON TRANSLATION. ═OST OF THE CONTROL CHARACTERS AND ALL OF THE
CHARACTERS OF VALUE 128 (0X80) OR GREATER ARE THROWN AWAY ON BEING
TRANSLATED. ╘HE TABLE IS SET UP SO THAT ├╥ CHARACTERS ARE THROWN AWAY AND THE
╠╞ CHARACTER IS TRANSLATED TO A ├┬═-─╧╙ ├╥ CHARACTER. ╘HUS, BOTH ═╙-─╧╙ ┴╙├╔╔
FILES AND ╒╬╔╪ ┴╙├╔╔ FILES CAN BE TRANSLATED CORRECTLY.
2. ┬╒╥╙╘ ├╧══┴╬─╙
╘HREE BURST COMMANDS FROM THE 1571/81 DISK DRIVE ┬URST ├OMMAND ╔NSTRUCTION ╙ET
ARE REQUIRED TO ALLOW THIS PROGRAM TO READ THE ═╙-─╧╙ DISKS: ╤UERY ─ISK
╞ORMAT, ╙ECTOR ╔NTERLEAVE, AND ╥EAD. ╘HE GRUNGY DETAILS ABOUT ISSUING BURST
COMMANDS AND BURST MODE HANDSHAKING ARE COVERED IN ├= ╚ACKING ╔SSUE #3. ╘HE
╤UERY ─ISK ╞ORMAT COMMAND IS USED TO "LOG IN" THE ═╙-─╧╙ DISK. ╘HE ╔NQUIRE
─ISK BURST COMMAND CANNOT BE USED WITH AN ═╙-─╧╙ DISK ON THE 1581 FOR SOME
UNKNOWN REASON. ╔ FOUND THIS OUT THE HARD WAY. ╘HE ╤UERY ─ISK ╞ORMAT COMMAND
HAS THE FOLLOWING FORMAT:
┬┘╘┼ \ BIT: 7 6 5 4 3 2 1 0 ▄ ╓ALUE
-------+--------+-----+-----+-----+-----+-----+-----+-----+-------
0 ▄ 0 ▄ 1 ▄ 0 ▄ 1 ▄ 0 ▄ 1 ▄ 0 ▄ 1 ▄ "╒"
1 ▄ 0 ▄ 0 ▄ 1 ▄ 1 ▄ 0 ▄ 0 ▄ 0 ▄ 0 ▄ "0"
2 ▄ ╞ ▄ ╪ ▄ ╪ ▄ ╙ ▄ 1 ▄ 0 ▄ 1 ▄ ╬ ▄ 10
-------+--------------------------------------------------+-------
WHERE THE ╞, ╙, AND ╬ BITS HAVE A VALUE OF 0 FOR OUR PURPOSES. ┴ RESPONSE OF
A BURST STATUS BYTE AND SIX OTHER THROW-AWAY BYTES IS GIVEN FROM THE DRIVE.
╘HIS COMMAND TAKES QUITE A LONG TIME TO EXECUTE ON MY 1581 BUT WORKS QUITE
QUICKLY ON MY 1571. ┘OU ONLY HAVE TO LOG IN A DISK WHENEVER YOU CHANGE
DISKS.
╘HE ╙ECTOR ╔NTERLEAVE COMMAND IS USED TO SET A SOFT INTERLEAVE FOR THE ╥EAD
COMMAND. ╔ USE AN INTERLEAVE OF 1 FOR THE 1581 AND AN INTERLEAVE OF 4 FOR THE
1571. ╘HIS MEANS THAT THE ═╙-─╧╙ SECTORS WILL COME FROM 1571 TO THE COMPUTER
IN THE FOLLOWING ORDER: 1, 5, 9, 4, 8, 3, 7, 2, 6 (THERE ARE 9 SECTORS PER
TRACK ON AN ═╙-─╧╙ DISK (BOTH 3.5" AND 5.25"), NUMBERED FROM 1 TO 9). ╠╥╥
HANDLES THE DATA COMING IN IN THIS ORDER, AND IN STRAIGHT ORDER FROM THE
1581. ╘HE ╙ECTOR ╔NTERLEAVE COMMAND HAS THE FOLLOWING FORMAT, WHERE THE ╫ AND
╬ BITS ARE 0 FOR US:
┬┘╘┼ \ BIT: 7 6 5 4 3 2 1 0 ▄ ╓ALUE
-------+--------+-----+-----+-----+-----+-----+-----+-----+-------
0 ▄ 0 ▄ 1 ▄ 0 ▄ 1 ▄ 0 ▄ 1 ▄ 0 ▄ 1 ▄ "╒"
1 ▄ 0 ▄ 0 ▄ 1 ▄ 1 ▄ 0 ▄ 0 ▄ 0 ▄ 0 ▄ "0"
2 ▄ ╫ ▄ ╪ ▄ ╪ ▄ 0 ▄ 1 ▄ 0 ▄ 0 ▄ ╬ ▄ 8
3 ▄ <INTERLEAVE> ▄ 1 OR 4
-------+--------------------------------------------------+-------
╘HE ╥EAD COMMAND IS USED TO TRANSFER THE NINE SECTORS OF A TRACK TO THE
COMPUTER IN THE ORDER SPECIFIED BY THE INTERLEAVE. ╘HE FORMAT IS:
┬┘╘┼ \ BIT: 7 6 5 4 3 2 1 0 ▄ ╓ALUE
-------+--------+-----+-----+-----+-----+-----+-----+-----+-------
0 ▄ 0 ▄ 1 ▄ 0 ▄ 1 ▄ 0 ▄ 1 ▄ 0 ▄ 1 ▄ "╒"
1 ▄ 0 ▄ 0 ▄ 1 ▄ 1 ▄ 0 ▄ 0 ▄ 0 ▄ 0 ▄ "0"
2 ▄ ╘/╠ ▄ ┼ ▄ ┬/╪ ▄ ╙ ▄ 0 ▄ 0 ▄ 0 ▄ ╬ ▄ 0 OR 16
3 ▄ <TRACK> ▄ ???
4 ▄ <SECTOR> ▄ 1
5 ▄ <NUMBER OF SECTORS> ▄ 9
-------+--------------------------------------------------+-------
╘HERE ARE A COUPLE OF DIFFERENCES BETWEEN THE 1571 AND 1581 VERSIONS OF THIS
COMMAND. ═OST IMPORTANT, THE ╙ BIT (╙IDE OF DISK TO USE) HAS THE OPPOSITE
MEANING ON THE TWO DRIVES. ╘HERE'S NO GOOD REASON THAT ╔ KNOW OF FOR THIS
INCONSISTENCY. ╘HIS IS THE REASON THAT ╠╥╥ NEEDS TO KNOW WHAT TYPE OF ═╙-─╧╙
DRIVE IT IS DEALING WITH (PLUS INTERLEAVING).
╘HE READ COMMAND RETURNS THE FOLLOWING DATA USING BURST MODE HANDSHAKING:
+-------------------+
0 ▄ ┬URST ╙TATUS ┬YTE ▄
+-------------------+
1 ▄ ▄
... + 512 ─ATA ┬YTES ▄
512 ▄ ▄
+-------------------+
FOR EACH SECTOR TRANSFERRED. ╔F THE ┬URST ╙TATUS ┬YTE INDICATES AN ERROR,
THEN THE DATA IS NOT TRANSFERRED AND NONE OF THE FOLLOWING SECTORS ARE
EITHER. ╔F THE STATUS BYTE GIVES A "─ISK ├HANGED" ERROR, THEN YOU HAVE TO LOG
IN THE DISK WITH THE ╤UERY ─ISK ╞ORMAT COMMAND BEFORE READ WILL WORK
PROPERLY. ╘HIS IS ACTUALLY A GOOD FEATURE SINCE IT LETS YOU KNOW ABOUT A DISK
CHANGE SO YOU CAN UPDATE ANY DATA STRUCTURES YOU MAY HAVE. ╠╥╥ SIMPLY RE-LOGS
IN THE DISK WITHOUT UPDATING ANY DATA STRUCTURES AND RE-TRIES THE FAILED READ
OPERATION.
3. ═╙-─╧╙ ─╔╙╦ ╞╧╥═┴╘
┴N ═╙-─╧╙ DISK IS SEPARATED INTO 4 DIFFERENT PARTS: THE ┬OOT ╙ECTOR, THE
╞┴╘(S), THE ╥OOT ─IRECTORY, AND THE ╞ILE ─ATA ╙ECTORS. ╘HE LOGICAL SECTORS
(BLOCKS) OF A DISK ARE NUMBERED FROM 0 TO SOME MAXIMUM NUMBER (1439 FOR A
3.5", 719 FOR A 5.25" ── DISK). ╘HE PHYSICAL LAYOUT AND THE LOGICAL SECTOR
NUMBERS TYPICALLY USED BY A 3.5" DISK ARE SHOWN HERE:
+-------------------+
0 ▄ ┬OOT ╙ECTOR ▄
+-------------------+
1..3 ▄ ╞┴╘ COPY #1 ▄
+-------------------+
4..6 ▄ ╞┴╘ COPY #2 ▄
+-------------------+
7..14 ▄ ╥OOT ─IRECTORY ▄
+-------------------+
15 ▄ ▄
... ▄ ╞ILE ─ATA ╙ECTORS ▄
1439 ▄ ▄
+-------------------+
3.1. ╘╚┼ ┬╧╧╘ ╙┼├╘╧╥
╘HE ┬OOT ╙ECTOR IS ALWAYS AT LOGICAL SECTOR NUMBER 0. ╔T CONTAINS SOME
IMPORTANT INFORMATION ABOUT THE FORMAT OF THE DISK AND IT ALSO CONTAINS CODE
TO BOOT AN ═╙-─╧╙ MACHINE FROM. ╫E AREN'T CONCERNED WITH THE BOOTSTRAPPING
CODE, BUT THE IMPORTANT VALUES WE NEED TO OBTAIN FROM THE BOOT SECTOR ARE:
┴┬┬╥ ╧╞╞╙┼╘ 1571 1581 ─┼╙├╥╔╨╘╔╧╬
---- ------ ---- ---- -----------
├╙ 13 2 2 ├LUSTER SIZE IN SECTORS
╬┬ 14 1 1 ╬UMBER OF BOOT SECTORS
╬╞ 16 2 2 ╬UMBER OF ╞┴╘S
╞╠ 23 2 3 ╞┴╘ SIZE IN SECTORS
─┼ 17 112 112 ╬UMBER OF ROOT DIRECTORY ENTRIES
╘╙ 19,20 720 1440 ╘OTAL ╬UMBER OF SECTORS
╬╙ 24 9 9 ╬UMBER OF SECTORS PER TRACK
╬╚ 26 2 2 ╬UMBER OF SIDES
╘HE 1571 AND 1581 COLUMNS GIVE THE TYPICAL VALUES OF THESE PARAMETERS FOR
5.25" AND 3.5" DISKS. ╘HE ╧╞╞╙┼╘ IS THE ADDRESS OF THE PARAMETER WITHIN THE
BOOT SECTOR. ╘HE TOTAL NUMBER OF SECTORS IS GIVEN IN LOW-BYTE, HIGH-BYTE
ORDER (SINCE THE 80X86 FAMILY IS LITTLE-ENDIAN LIKE THE 6502 FAMILY). ╞ROM
THE ABOVE PARAMETERS, WE CAN DERIVE THE FOLLOWING IMPORTANT PARAMETERS:
┴┬┬╥ ╞╧╥═╒╠┴ 1571 1581 ─┼╙├╥╔╨╘╔╧╬
---- ------- ---- ---- -----------
╞1 ╬┬+╬╞*╞╠ 5 7 ╞IRST ROOT DIRECTORY SECTOR
╞╙ ╬┬+╬╞*╞╠+─┼ 12 14 ╞IRST FILE DATA SECTOR NUMBER
╬├ (╘╙-╞╙)/├╙ 354 713 ╘OTAL NUMBER OF FILE CLUSTERS
╠╥╥ IMPOSES A NUMBER OF LIMITS ON THESE PARAMETERS AND WILL ERROR-OUT IF YOU
TRY TO USE A DISK THAT IS OUTSIDE OF ╠╥╥'S LIMITS.
3.2. ├╚┼╫╔╬╟ ╘╚┼ ╞┴╘
═╙-─╧╙ DISKS USE A DATA STRUCTURE CALLED A ╞ILE ┴LLOCATION ╘ABLE (╞┴╘) TO
RECORD WHICH CLUSTERS BELONG TO WHICH FILE IN WHAT ORDER AND WHICH BLOCKS ARE
FREE. ┴ CLUSTER IS A SET OF CONTIGUOUS SECTORS WHICH ARE ALLOCATED TO FILES
AS A GROUP. ╠╥╥ HANDLES CLUSTER SIZES OF 1 AND 2 SECTORS, GIVING A LOGICAL
FILE BLOCK SIZE OF 512 OR 1024 BYTES. ╘YPICALLY, A CLUSTER SIZE OF 2 SECTORS
IS USED.
╘HE ╞┴╘ IS AN ARRAY OF 12-BIT NUMBERS, WITH AN ENTRY CORRESPONDING TO EACH
CLUSTER THAT CAN BE ALLOCATED TO FILES. ╞┴╘ ENTRIES 0 AND 1 ARE RESERVED. ╔F
A ╞┴╘ ENTRY CONTAINS A VALUE OF $000, THEN THE CORRESPONDING CLUSTER IS FREE
AND CAN BE ALLOCATED TO A FILE; OTHERWISE, THE CLUSTER IS ALLOCATED AND THE
╞┴╘ ENTRY CONTAINS THE NUMBER OF THE ╬┼╪╘ ╞┴╘ ENTRY THAT BELONGS TO THE FILE.
╘HUS, ═╙-─╧╙ FILES ARE STORED IN A SINGLY-LINKED LIST OF CLUSTERS LIKE
├OMMODORE-─╧╙ FILES ARE, EXCEPT THAT THE LINKS ARE NOT IN THE DATA SECTORS BUT
RATHER ARE IN THE ╞┴╘. ╘HE POINTER TO THE FIRST ╞┴╘ ENTRY FOR A FILE IS GIVEN
IN THE FILE'S DIRECTORY ENTRY.
┴ SPECIAL ╬╒╠╠/╬╔╠ POINTER VALUE OF $╞╞╞ IS USED TO INDICATE THE END OF THE
CHAIN OF CLUSTERS ALLOCATED TO A FILE. ╘HIS VALUE IS STORED IN THE ╞┴╘ ENTRY
OF THE LAST CLUSTER ALLOCATED TO A FILE (OF COURSE). ├ONSIDER THE FOLLOWING
EXAMPLE ╞┴╘:
┼╬╘╥┘ ╓┴╠╒┼
----- -----
$000 $╞╞╞
$001 $╞╞╞
$002 ▄----$003 <------─IRECTORY ┼NTRY
$003 +--> $005----+
$004 $000 ▄
$005 $╞╞╞ <--+
┼NTRIES 0 AND 1 ARE INSIGNIFICANT SINCE THEY ARE RESERVED. ╙AY THAT A FILE
STARTS AT ╞┴╘ ENTRY #2. ╘HEN, IT CONSISTS OF THE FOLLOWING CHAIN OF CLUSTERS:
2, 3, AND 5. ├LUSTER #4 IS FREE. ├LUSTERS CAN BE ALLOCATED TO A FILE IN
RANDOM ORDER, BUT IF THEY ARE ALLOCATED CONTIGUOUSLY IN FORWARD ORDER, THEN
THE FILE WILL BE ABLE TO BE READ FASTER. ╘HE ╞┴╘ IS SUCH AN IMPORTANT DATA
STRUCTURE THAT TYPICALLY TWO COPIES ARE KEPT ON THE DISK INCASE ONE OF THEM
SHOULD BECOME CORRUPTED.
╘HE ═╙-─╧╙ DESIGNERS WERE A LITTLE SNEAKY IN STORING THE 12-BIT ╞┴╘ ENTRIES -
THEY USED ONLY 12 REAL BITS PER ENTRY. ╔E., THEY STORE TWO ╞┴╘ ENTRIES IN
THREE BYTES, WHERE THE TWO ENTRIES SHARE THE TWO NYBBLES OF THE MIDDLE BYTE.
╘HE FOLLOWING DIAGRAM SHOWS HOW THE NYBBLES 1 (HIGH), 2 (MID), AND 3 (LOW) ARE
STORED INTO ╞┴╘ ENTRIES ┴ AND ┬:
┬┘╘┼: 0 1 2
+---+---+ +---+---+ +---+---+
┼╬╘╥┘: ▄ ┴ ▄ ┴ ▄ ▄ ┬ ▄ ┴ ▄ ▄ ┬ ▄ ┬ ▄
╬┘┬┬╠┼: ▄ 2 ▄ 3 ▄ ▄ 3 ▄ 1 ▄ ▄ 1 ▄ 2 ▄
+---+---+ +---+---+ +---+---+
┴NYWAY, LET'S JUST SAY IT'S A BIT TRICKY TO EXTRACT THE 12-BIT VALUES FROM
THIS COMPRESSED DATA STRUCTURE. ╧N TOP OF THAT, ╔ DON'T THINK THERE IS ANY
SAVING IN DISK SPACE RESULTING FROM COMPRESSING THIS STRUCTURE; THEY MIGHT AS
WELL HAVE JUST USED A 16-BIT ╞┴╘ (LIKE THEY DO NOWADAYS ON LARGER DISKS).
3.3. ╘╚┼ ╥╧╧╘ ─╔╥┼├╘╧╥┘
╘HE ROOT DIRECTORY HAS A FIXED SIZE, ALTHOUGH ╔ DON'T THINK THAT
SUBDIRECTORIES DO. ╠╥╥ CANNOT ACCESS SUBDIRECTORIES. ┼ACH 512-BYTE SECTOR OF
THE ROOT DIRECTORY CONTAINS SIXTEEN 32-BYTE DIRECTORY ENTRIES. ╧NE DIRECTORY
ENTRY IS REQUIRED FOR EACH FILE STORED ON THE DISK. ┴ DIRECTORY ENTRY HAS THE
FOLLOWING STRUCTURE:
╧╞╞╙┼╘ ╠┼╬ ─┼╙├╥╔╨╘╔╧╬
------ --- -----------
0..7 8 ╞ILENAME
8..10 3 ┼XTENSION
11 1 <UNUSED?>
12 1 ┴TTRIBUTES: $10=─IRECTORY, $08=╓OLUME╔D
13..21 9 <UNUSED>
22..25 4 ─ATE
26..27 2 ╙TARTING ╞┴╘ ENTRY NUMBER
28..31 4 ╞ILE LENGTH IN BYTES
╘HE FILENAME AND EXTENSION ARE STORED WITH TRAILING PADDING SPACES. ╔F A
DIRECTORY ENTRY IS UNUSED OR DELETED, THEN THE FIRST CHARACTER OF THE FILENAME
IS EITHER A $00 OR A $┼5 (229). ╘HIS IS WHY YOU HAVE TO PROVIDE THE FIRST
CHARACTER OF A FILENAME IF YOU ARE UNDELETING A FILE ON AN ═╙-─╧╙ MACHINE.
╬OTE THAT THERE IS ENOUGH UNUSED SPACE THAT ═ICROSOFT OR ╔┬═ COULD HAVE
DITCHED THE ANNOYING 8+3 CHARACTER FILENAME FORMAT.
╘HE ATTRIBUTES BITS TELL WHETHER THE DIRECTORY ENTRY IS FOR A REGULAR FILE, A
SUBDIRECTORY, A DISK VOLUME NAME (IN WHICH CASE THERE IS NO FILE DATA), AND A
COUPLE OF OTHER THINGS ╔ CAN'T REMEMBER. ╔'M NOT SURE ABOUT THE EXACT
POSITION OR FORMAT OF THE DATE, BUT ╠╥╥ DOESN'T USE IT ANYWAY. ╘HE STARTING
╞┴╘ ENTRY NUMBER AND THE FILE LENGTH ARE STORED IN LOWER-BYTE-FIRST ORDER.
3.4. ╘╚┼ ╞╔╠┼ ─┴╘┴ ╙╨┴├┼
╘HE RAMAINDER OF THE DISK SPACE IS USED FOR STORING FILE DATA IN CLUSTERS OF 1
OR 2 SECTORS EACH. ╟IVEN A CLUSTER NUMBER (WHICH IS ALSO THE ╞┴╘ ENTRY
NUMBER), THE FOLLOWING FORMULA IS USED TO CALCULATE THE STARTING LOGICAL
SECTOR NUMBER OF THE CLUSTER:
(├LUSTER╬UMBER - 2) * ├LUSTER╙IZE╔N┬LOCKS + ╞IRST╞ILE─ATA╠OGICAL╙ECTOR╬UMBER
WHERE "╞IRST╞ILE─ATA╠OGICAL╙ECTOR╬UMBER" IS THE "╞╙" PARAMETER DERIVED
EARLIER. ╘HE FOLLOWING CONSECUTIVE LOGICAL SECTOR NUMBERS UP TO THE NUMBER OF
SECTORS PER CLUSTER FORM THE REST OF THE CLUSTER. ╬OTE THAT A SINGLE CLUSTER
CAN SPAN SECTORS FROM ONE SIDE OF THE DISK TO ANOTHER OR FROM ONE TRACK TO
ANOTHER. ╫E PERFORM THE "(├LUSTER╬UMBER - 2)" PORTION OF THE CALCULATION
SINCE THE FIRST TWO ╞┴╘ ENTRIES ARE RESERVED.
╙INCE THE ╥EAD BURST COMMAND OF THE 1571/81 WANTS THE SIDE, TRACK, AND SECTOR
NUMBER OF A SECTOR RATHER THAN ITS LOGICAL NUMBER, WE ALSO NEED FORMULAE FOR
THESE CONVERSIONS:
╘RACK = ╠OGICAL╙ECTOR╬UMBER / 18
╙ECTOR = ╠OGICAL╙ECTOR╬UMBER % 9 + 1
╙IDE = (╠OGICAL╙ECTOR╬UMBER / 9) % 2
╘HESE FORMULAE ARE MORE PROBLEMATIC THAN THE PREVIOUS ONE SINCE THEY REQUIRE
DIVISION BY 9 AND 18. ╠╥╥ USES THE METHOD OF REPEATED SUBTRACTION TO PERFROM
THE NECESSARY DIVISION (ONLY ONE DIVISION IS NECESSARY). ╘HE ABOVE FORMULAE
IMPLY THAT SEQUENTIAL LOGICAL SECTORS ARE STORED ON THE TOP OF THE DISK
FIRST AND THEN THE BOTTOM OF THE DISK OF THE SAME TRACK, AND THEN ON THE TOP
OF THE NEXT TRACK, ETC. ╘HIS IS A GOOD SECTOR NUMBERING SCHEME (UNLIKE THE
├┬═-─╧╙ SCHEME FOR 1571 SECTORS) SINCE IT IS FASTER TO SWITCH SIDES OF THE
DISK THAN IT IS TO SWITCH TRACKS, SO YOU CAN READ THE DISK FASTER.
╧H YEAH, THE WAY THAT YOU KNOW HOW MANY FILE DATA BYTES ARE IN THE LAST
CLUSTER OF A FILE CHAIN (THE CLUSTER WITH THE ╬╒╠╠ ╞┴╘ ENTRY) IS TO TAKE THE
FILE LENGTH FROM THE DIRECTORY ENTRY AND "MOD" (THE ├ LANGUAGE % OPERATOR) IT
WITH THE CLUSTER SIZE. ╧NE SPECIAL CASE IS IF THIS CALCULATION RESULTS IN A
ZERO, THEN THE LAST CLUSTER IS COMPLETELY FULL (RATHER THAN COMPLETELY EMPTY
AS THE CALCULATION WOULD SUGGEST). ╘HIS CALCULATION IS EASILY DONE IN
MACHINE LANGUAGE WITH AN ┴╬─ OPERATION SINCE THE CLUSTER SIZE IS ALWAYS A
POWER OF TWO.
4. ╞╔╠┼ ├╧╨┘╔╬╟ ╨┴├╦┴╟┼
╘HIS SECTION DISCUSSES THE INTERFACE TO AND IMPLEMENTATION OF THE ═╙-─╧╙ FILE
COPYING PACKAGE. ╔T IS WRITTEN IN ASSEMBLY LANGUAGE AND IS LOADED INTO MEMORY
AT ADDRESS $8000 ON BANK 0 AND REQUIRES ABOUT 13╦ OF MEMORY. ╘HE PACKAGE IS
LOADED AT THIS HIGH ADDRESS TO BE OUT OF THE WAY OF THE MAIN ┬┴╙╔├ PROGRAM,
EVEN IF ╥┴═─╧╙ IS INSTALLED.
4.1. ╔╬╘┼╥╞┴├┼
╘HE SUBROUTINE CALL AND PARAMETER PASSING INTERFACE TO THE FILE COPYING
PACKAGE IS SUMMARIZED AS FOLLOWS:
┴──╥┼╙╙ ─┼╙├╥╔╨╘╔╧╬
------- -----------
╨╦ ╔NIT╨ACKAGE SUBROUTINE
╨╦+3 ╠OAD─IRECTORY SUBROUTINE
╨╦+6 ├OPY╞ILE SUBROUTINE
╨╦+9 TWO-BYTE PACKAGE IDENTIFICATION NUMBER
╨╦+15 ERRNO : ERROR CODE RETURNED
╨╦+16 ═╙-─╧╙ DEVICE NUMBER (8 TO 30)
╨╦+17 ═╙-─╧╙ DEVICE TYPE ($00=1571, $╞╞=1581)
╨╦+18 TWO-BYTE STARTING CLUSTER NUMBER FOR FILE COPYING
╨╦+20 LOW AND MID BYTES OF FILE LENGTH FOR COPYING
WHERE "╨╦" IS THE LOAD ADDRESS OF THE PACKAGE. ┴DDITIONAL SUBROUTINE
PARAMETERS ARE PASSED IN THE PROCESSOR REGISTERS.
╘HE "╔NIT╨ACKAGE" SUBROUTINE SHOULD BE CALLED WHEN THE PACKAGE IS FIRST
INSTALLED, WHENEVER THE ═╙-─╧╙ DEVICE NUMBER IS CHANGED, AND WHENEVER A NEW
DISK IS MOUNTED TO INVALIDATE THE INTERNAL TRACK CACHE. ╔T REQUIRES NO
PARAMETERS.
╘HE "╠OAD─IRECTORY" SUBROUTINE WILL LOAD THE DIRECTORY, ╞┴╘, AND THE ┬OOT
╙ECTOR PARAMETERS INTO THE INTERNAL MEMORY OF THE PACKAGE FROM THE CURRENT
═╙-─╧╙ DEVICE NUMBER. ╬O (OTHER) INPUT PARAMETERS ARE NEEDED AND THE
SUBROUTINE RETURNS A POINTER TO THE DIRECTORY SPACE IN THE .┴┘ REGISTERS AND
THE NUMBER OF DIRECTORY ENTRIES IN THE .╪ REGISTER. ╔F AN ERROR OCCURS, THEN
THE SUBROUTINE RETURNS WITH THE ├ARRY FLAG SET AND THE ERROR CODE IS AVAILABLE
IN THE "ERRNO" INTERFACE VARIABLE. ╘HE DIRECTORY ENTRY DATA IS IN THE
DIRECTORY SPACE AS IT WAS READ IN RAW FROM THE DIRECTORY SECTORS ON THE ═╙-─╧╙
DISK.
╘HE "├OPY╞ILE" SUBROUTINE WILL COPY A SINGLE FILE FROM THE ═╙-─╧╙ DISK TO A
SPECIFIED ├┬═-╦ERNAL LOGICAL FILE NUMBER (THE ├┬═ FILE MUST ALREADY BE
OPENED). ╔F THE ├┬═ LOGICAL FILE NUMBER IS ZERO, THEN THE FILE DATA IS SIMPLY
DISCARDED AFTER IT IS READ FROM THE ═╙-─╧╙ FILE. ╘HE STARTING CLUSTER NUMBER
OF THE FILE TO COPY AND THE LOW AND MID BYTES OF THE FILE LENGTH ARE PASSED IN
THE ╨╦+18 AND ╨╦+20 INTERFACE WORDS. ╘HE TRANSLATION MODE TO USE IS PASSED IN
THE .┴ REGISTER ($00=BINARY, $╞╞=ASCII) AND THE ├┬═ LOGICAL FILE NUMBER TO
OUTPUT TO IS PASSED IN THE .╪ REGISTER. ╔F AN ERROR OCCURS, THE ROUTINE
RETURNS WITH THE ├ARRY FLAG SET AND THE ERROR CODE IN THE "ERRNO" INTERFACE
VARIABLE. ╘HERE ARE NO OTHER OUTPUT PARAMETERS.
╬OTE THAT SINCE THE STARTING CLUSTER NUMBER AND LOW-FILE LENGTH OF THE FILE TO
BE COPIED ARE REQUIRED RATHER THAN THE FILENAME, IT IS THE RESPONSIBILITY OF
THE FRONT-END APPLICATION PROGRAM TO DIG THROUGH THE RAW DIRECTORY SECTOR DATA
TO GET THIS INFORMATION. ╘HE APPLICATION MUST ALSO OPEN THE ├OMMODORE-─╧╙
FILE OF WHATEVER FILETYPE ON WHATEVER DEVICE IS REQUIRED; THE PACKAGE DOES NOT
NEED TO KNOW THE ├OMMODORE-─╧╙ DEVICE NUMBER.
╘HE ═╙-─╧╙ DEVICE NUMBER AND DEVICE TYPE INTERFACE VARIABLES ALLOW YOU TO SET
THE ═╙-─╧╙ DRIVE AND THE PACKAGE IDENTIFICATION NUMBER ALLOWS THE APPLICATION
PROGRAM TO CHECK IF THE PACKAGE IS ALREADY LOADED INTO MEMORY SO THAT IT ONLY
HAS TO LOAD THE PACKAGE THE FIRST TIME THE APPLICATION IS RUN AND NOT ON
RE-RUNS. ╘HE IDENTIFICATION SEQUENCE IS A VALUE OF $├┬ FOLLOWED BY A VALUE
OF 131.
4.2. ╔═╨╠┼═┼╬╘┴╘╔╧╬
╘HIS SECTION PRESENTS THE CODE THAT IMPLEMENTS THE ═╙-─╧╙ FILE READING
PACKAGE. ╔T IS HERE IN A SPECIAL FORM; EACH CODE LINE IS PRECEDED BY A FEW
SPECIAL CHARACTERS AND THE LINE NUMBER. ╘HE SPECIAL CHARACTERS ARE THERE TO
ALLOW YOU TO EASILY EXTRACT THE ASSEMBLER CODE FROM THE REST OF THIS MAGAZINE
(AND ALL OF MY UGLY COMMENTS). ╧N A ╒NIX SYSTEM, ALL YOU HAVE TO DO IS
EXECUTE THE FOLLOWING COMMAND LINE (SUBSTITUTE FILENAMES AS APPROPRIATE):
GREP '^\.%...\!' ╚ACK4 ▄ SED 'S/^.%...\!..//' ▄ SED 'S/.%...\!//' >LRR.S
┘OU'LL NOTICE THAT THE INITIAL COMMENT LINES HERE WERE AN AFTERTHOUGHT.
.%000! ;╠ITTLE ╥ED ╥EADER ═╙-─╧╙ FILE COPIER PROGRAM
.%000! ;WRITTEN 92/10/03 BY ├RAIG ┬RUCE FOR ├= ╚ACKING ╬ET ═AGAZINE
.%000!
╘HE CODE IS WRITTEN FOR THE ┬UDDY ASSEMBLER AND HERE ARE A COUPLE SETUP
DIRECTIVES. ╬OTE THAT MY COMMENTS COME BEFORE THE SECTION OF CODE.
.%001! .ORG $8000
.%002! .OBJ "@:LRR.BIN"
.%003!
.%004! ;====JUMP TABLE AND PARAMETERS INTERFACE ====
.%005!
.%006! JMP INIT╨ACKAGE
.%007! JMP LOAD─IRECTORY
.%008! JMP COPY╞ILE
.%009!
.%010! .BYTE $CB,131 ;IDENTIFICATION
.%011! .BYTE 0,0,0,0
.%012!
╘HESE VARIABLES ARE INCLUDED IN THE PACKAGE PROGRAM SPACE TO MINIMIZE UNWANTED
INTERACTION WITH OTHER PROGRAMS LOADED AT THE SAME TIME, SUCH AS THE ╥┴═─╧╙
DEVICE DRIVER.
.%013! ERRNO .BUF 1 ;(LOCATION PK+15)
.%014! SOURCE─EVICE .BUF 1
.%015! SOURCE╘YPE .BUF 1 ;$00=1571, $FF=1581
.%016! START├LUSTER .BUF 2
.%017! LEN═╠ .BUF 2 ;LENGTH MEDIUM AND LOW BYTES
.%018!
.%019! ;====GLOBAL DECLARAIONS====
.%020!
.%021! KERNEL╠ISTEN = $FFB1
.%022! KERNEL╙ECOND = $FF93
.%023! KERNEL╒NLSN = $FFAE
.%024! KERNEL┴CPTR = $FFA2
.%025! KERNEL├IOUT = $FFA8
.%026! KERNEL╙PINP = $FF47
.%027! KERNEL├HKOUT = $FFC9
.%028! KERNEL├LRCHN = $FFCC
.%029! KERNEL├HROUT = $FFD2
.%030!
.%031! ST = $D0
.%032! CIA├LOCK = $DD00
.%033! CIA╞LAGS = $DC0D
.%034! CIA─ATA = $DC0C
.%035!
╘HESE ARE THE PARAMETERS AND DERIVED PARAMETERS FROM THE BOOT SECTOR. ╘HEY
ARE KEPT IN THE PROGRAM SPACE TO AVOID INTERACTIONS.
.%036! CLUSTER┬LOCK├OUNT .BUF 1 ;1 OR 2
.%037! FAT┬LOCKS .BUF 1 ;UP TO 3
.%038! ROOT─IR┬LOCKS .BUF 1 ;UP TO 8
.%039! ROOT─IR┼NTRIES .BUF 1 ;UP TO 128
.%040! TOTAL╙ECTORS .BUF 2 ;UP TO 1440
.%041! FIRST╞ILE┬LOCK .BUF 1
.%042! FIRST╥OOT─IR┬LOCK .BUF 1
.%043! FILE├LUSTER├OUNT .BUF 2
.%044!
╘HE CYLINDER (TRACK) AND SIDE THAT IS CURRENTLY STORED IN THE TRACH CACHE.
.%045! BUF├YLINDER .BUF 1
.%046! BUF╙IDE .BUF 1
.%047! FORMAT╨ARMS .BUF 6
.%048!
╘HIS PACKAGE IS SPLIT INTO A NUMBER OF LEVELS. ╘HIS LEVEL INTERFACES WITH THE
╦ERNAL SERIAL BUS ROUTINES AND THE BURST COMMAND PROTOCOL OF THE DISK DRIVES.
.%049! ;====HARDWARE LEVEL====
.%050!
├ONNECT TO THE ═╙-─╧╙ DEVICE AND SEND THE "╒0" BURST COMMAND PREFIX AND THE
BURST COMMAND BYTE.
.%051! SEND╒0 = * ;( .┴=BURST├OMMAND├ODE ) : .├╙=ERR
.%052! PHA
.%053! LDA #0
.%054! STA ST
.%055! LDA SOURCE─EVICE
.%056! JSR KERNEL╠ISTEN
.%057! LDA #$6F
.%058! JSR KERNEL╙ECOND
.%059! LDA #"U"
.%060! JSR KERNEL├IOUT
.%061! BIT ST
.%062! BMI SEND╒0┼RROR
.%063! LDA #"0"
.%064! JSR KERNEL├IOUT
.%065! PLA
.%066! JSR KERNEL├IOUT
.%067! BIT ST
.%068! BMI SEND╒0┼RROR
.%069! CLC
.%070! RTS
.%071!
.%072! SEND╒0┼RROR = *
.%073! LDA #5
.%074! STA ERRNO
.%075! SEC
.%076! RTS
.%077!
╘OGGLE THE "─ATA ┴CCEPTED / ╥EADY ╞OR ═ORE" CLOCK SIGNAL FOR THE BURST
TRANSFER PROTOCOL.
.%078! TOGGLE├LOCK = *
.%079! LDA CIA├LOCK
.%080! EOR #$10
.%081! STA CIA├LOCK
.%082! RTS
.%083!
╫AIT FOR A BURST BYTE TO ARRIVE IN THE SERIAL DATA REGISTER OF ├╔┴#1 FROM THE
FAST SERIAL BUS.
.%084! SERIAL╫AIT = *
.%085! LDA #$08
.%086! - BIT CIA╞LAGS
.%087! BEQ -
.%088! RTS
.%089!
╫AIT FOR AND GET A BURST BYTE FROM THE FAST SERIAL BUS, AND SEND THE "─ATA
┴CCEPTED" SIGNAL.
.%090! GET┬URST┬YTE = *
.%091! JSR SERIAL╫AIT
.%092! LDX CIA─ATA
.%093! JSR TOGGLE├LOCK
.%094! TXA
.%095! RTS
.%096!
╙END THE BURST COMMANDS TO "LOG IN" THE ═╙-─╧╙ DISK AND SET THE ╥EAD SECTOR
INTERLEAVE FACTOR.
.%097! MOUNT─ISK = * ;() : .├╙=ERR
.%098! LDA #%00011010
.%099! JSR SEND╒0
.%100! BCC +
.%101! RTS
.%102! + JSR KERNEL╒NLSN
.%103! BIT ST
.%104! BMI SEND╒0┼RROR
.%105! CLC
.%106! JSR KERNEL╙PINP
.%107! BIT CIA╞LAGS
.%108! JSR TOGGLE├LOCK
.%109! JSR GET┬URST┬YTE
.%110! STA ERRNO
.%111! AND #$0F
.%112! CMP #2
.%113! BCS MOUNT┼XIT
╟RAB THE THROW-AWAY PARAMETERS FROM THE MOUNT OPERATION.
.%114! LDY #0
.%115! - JSR GET┬URST┬YTE
.%116! STA FORMAT╨ARMS,Y
.%117! INY
.%118! CPY #6
.%119! BCC -
.%120! CLC
╙ET THE SECTOR INTERLEAVE TO 1 FOR A 1581 OR 4 FOR A 1571.
.%121! ;** SET INTERLEAVE
.%122! LDA #%00001000
.%123! JSR SEND╒0
.%124! BCC +
.%125! RTS
.%126! + LDA #1 ;INTERLEAVE OF 1 FOR 1581
.%127! BIT SOURCE╘YPE
.%128! BMI +
.%129! LDA #4 ;INTERLEAVE OF 4 FOR 1571
.%130! + JSR KERNEL├IOUT
.%131! JSR KERNEL╒NLSN
.%132! MOUNT┼XIT = *
.%133! RTS
.%134!
╥EAD ALL OF THE SECTORS OF A GIVEN TRACK INTO THE TRACK CACHE.
.%135! BUFPTR = 2
.%136! SECNUM = 4
.%137!
.%138! READ╘RACK = * ;( .┴=CYLINDER, .╪=SIDE ) : TRACKBUF, .├╙=ERR
.%139! PHA
.%140! TXA
╟ET THE SIDE AND PUT IT INTO THE COMMAND BYTE. ╥EMEMBER THAT WE HAVE TO FLIP
THE SIDE BIT FOR A 1581.
.%141! AND #$01
.%142! ASL
.%143! ASL
.%144! ASL
.%145! ASL
.%146! BIT SOURCE╘YPE
.%147! BPL +
.%148! EOR #$10
.%149! + JSR SEND╒0
.%150! BCC +
.%151! RTS
.%152! + PLA ;CYLINDER NUMBER
.%153! JSR KERNEL├IOUT
.%154! LDA #1 ;START SECTOR NUMBER
.%155! JSR KERNEL├IOUT
.%156! LDA #9 ;SECTOR COUNT
.%157! JSR KERNEL├IOUT
.%158! JSR KERNEL╒NLSN
╨REPARE TO RECEIVE THE TRACK DATA.
.%159! SEI
.%160! CLC
.%161! JSR KERNEL╙PINP
.%162! BIT CIA╞LAGS
.%163! JSR TOGGLE├LOCK
.%164! LDA #<TRACKBUF
.%165! LDY #>TRACKBUF
.%166! STA BUFPTR
.%167! STY BUFPTR+1
╟ET THE SECTOR DATA FOR EACH OF THE 9 SECTORS OF THE TRACK.
.%168! LDA #0
.%169! STA SECNUM
.%170! - BIT SOURCE╘YPE
.%171! BMI +
╔F WE ARE DEALING WITH A 1571, WE HAVE TO SET THE BUFFER POINTER FOR THE NEXT
SECTOR, TAKING INTO ACCOUNT THE SOFT INTERLEAVE OF 4.
.%172! JSR GET1571┬UF╨TR
.%173! + JSR READ╙ECTOR
.%174! BCS TRACK┼XIT
.%175! INC SECNUM
.%176! LDA SECNUM
.%177! CMP #9
.%178! BCC -
.%179! CLC
.%180! TRACK┼XIT = *
.%181! CLI
.%182! RTS
.%183!
╟ET THE BUFFER POINTER FOR THE NEXT 1571 SECTOR.
.%184! GET1571┬UF╨TR = *
.%185! LDA #<TRACKBUF
.%186! STA BUFPTR
.%187! LDX SECNUM
.%188! CLC
.%189! LDA #>TRACKBUF
.%190! ADC BUFPTR1571,X
.%191! STA BUFPTR+1
.%192! RTS
.%193!
.%194! BUFPTR1571 = *
.%195! .BYTE 0,8,16,6,14,4,12,2,10
.%196!
╥EAD AN INDIVIDUAL SECTOR INTO MEMORY AT THE SPECIFIED ADDRESS.
.%197! READ╙ECTOR = * ;( BUFPTR ) : .├╙=ERR
╟ET AND CHECK THE BURST STATUS BYTE FOR ERRORS.
.%198! JSR GET┬URST┬YTE
.%199! STA ERRNO
.%200! AND #$0F
.%201! CMP #2
.%202! BCC +
.%203! RTS
.%204! + LDX #2
.%205! LDY #0
.%206!
╥ECEIVE THE 512 SECTOR DATA BYTES INTO MEMORY.
.%207! READ┬YTE = *
.%208! LDA #$08
.%209! - BIT CIA╞LAGS
.%210! BEQ -
.%211! LDA CIA├LOCK
.%212! EOR #$10
.%213! STA CIA├LOCK
.%214! LDA CIA─ATA
.%215! STA (BUFPTR),Y
.%216! INY
.%217! BNE READ┬YTE
.%218! INC BUFPTR+1
.%219! DEX
.%220! BNE READ┬YTE
.%221! RTS
.%222!
╘HIS NEXT LEVEL OF ROUTINES DEALS WITH LOGICAL SECTORS AND THE TRACK CACHE
RATHER THAN WITH HARDWARE.
.%223! ;====LOGICAL SECTOR LEVEL====
.%224!
╔NVALIDATE THE TRACK CACHE IF THE ═╙-─╧╙ DRIVE NUMBER IS CHANGED OR IF A NEW
DISK IS INSERTED. ╘HIS ROUTINE HAS TO ESTABLISH A ╥┴═ CONFIGURATION OF $0┼
SINCE IT WILL BE CALLED FROM ╥┴═0. ├ONFIGURATION $0┼ GIVES ╥┴═0 FROM $0000 TO
$┬╞╞╞, ╦ERNAL ╥╧═ FROM $├000 TO $╞╞╞╞, AND THE ╔/╧ SPACE OVER THE ╦ERNAL FROM
$─000 TO $─╞╞╞. ╘HIS CONFIGURATION IS SET BY ALL APPLICATION INTERFACE
SUBROUTINES.
.%225! INIT╨ACKAGE = *
.%226! LDA #$0E
.%227! STA $FF00
.%228! LDA #$FF
.%229! STA BUF├YLINDER
.%230! STA BUF╙IDE
.%231! CLC
.%232! RTS
.%233!
╠OCATE A SECTOR (BLOCK) IN THE TRACK CACHE, OR READ THE CORRESPONDING PHYSICAL
TRACK INTO THE TRACK CACHE IF NECESSARY. ╘HIS ROUTINE ACCEPTS THE CYLINDER,
SIDE, AND SECTOR NUMBERS OF THE BLOCK.
.%234! SECTOR╙AVE = 5
.%235!
.%236! READ┬LOCK = * ;( .┴=CYLINDER,.╪=SIDE,.┘=SECTOR ) : .┴┘=BLK╨TR,.├╙=ERR
├HECK IF THE CORRECT TRACK IS IN THE TRACK CACHE.
.%237! CMP BUF├YLINDER
.%238! BNE READ┬LOCK╨HYSICAL
.%239! CPX BUF╙IDE
.%240! BNE READ┬LOCK╨HYSICAL
╔F SO, THEN LOCATE THE SECTOR'S ADDRESS AND RETURN THAT.
.%241! DEY
.%242! TYA
.%243! ASL
.%244! CLC
.%245! ADC #>TRACKBUF
.%246! TAY
.%247! LDA #<TRACKBUF
.%248! CLC
.%249! RTS
.%250!
╚ERE, WE HAVE TO READ THE PHYSICAL TRACK INTO THE TRACK CACHE. ╫E SAVE THE
INPUT PARAMETERS AND CALL THE HARDWARE-LEVEL TRACK-READING ROUTINE.
.%251! READ┬LOCK╨HYSICAL = *
.%252! STA BUF├YLINDER
.%253! STX BUF╙IDE
.%254! STY SECTOR╙AVE
.%255! JSR READ╘RACK
├HECK FOR ERRORS.
.%256! BCC READ┬LOCK╨HYSICAL╧K
.%257! LDA ERRNO
.%258! AND #$0F
.%259! CMP #11 ;DISK CHANGE
.%260! BEQ +
.%261! SEC
.%262! RTS
╔F THE ERROR THAT HAPPENED IS A "─ISK ├HANGE" ERROR, THEN MOUNT THE DISK AND
TRY TO READ THE PHYSICAL TRACK AGAIN.
.%263! + JSR MOUNT─ISK
.%264! LDA BUF├YLINDER
.%265! LDX BUF╙IDE
.%266! LDY SECTOR╙AVE
.%267! BCC READ┬LOCK╨HYSICAL
.%268! RTS
.%269!
╚ERE, THE PHYSICAL TRACK HAS BEEN READ INTO THE TRACK CACHE OK, SO WE RECOVER
THE ORIGINAL INPUT PARAMETERS AND TRY THE TOP OF THE ROUTINE AGAIN.
.%270! READ┬LOCK╨HYSICAL╧K = *
.%271! LDA BUF├YLINDER
.%272! LDX BUF╙IDE
.%273! LDY SECTOR╙AVE
.%274! JMP READ┬LOCK
.%275!
─IVIDE THE GIVEN NUMBER BY 18. ╘HIS IS NEEDED FOR THE CALCULATIONS TO CONVERT
A LOGICAL SECTOR NUMBER TO THE CORRESPONDING PHYSICAL CYLINDER, SIDE, AND
SECTOR NUMBERS THAT THE LOWER-LEVEL ROUTINES REQUIRE. ╘HE METHOD OF REPEATED
SUBTRACTION IS USED. ╘HIS ROUTINE WOULD PROBABLY WORK FASTER IF WE TRIED TO
REPEATEDLY SUBTRACT 360 (18*20) AT THE TOP, BUT ╔ DIDN'T BOTHER.
.%276! DIVIDE┬Y18 = * ;( .┴┘=NUMBER ) : .┴=QUOTIENT, .┘=REMAINDER
.%277! ;** COULD REPEATEDLY SUBTRACT 360 HERE
.%278! LDX #$FF
.%279! - INX
.%280! SEC
.%281! SBC #18
.%282! BCS -
.%283! DEY
.%284! BPL -
.%285! CLC
.%286! ADC #18
.%287! INY
.%288! TAY
.%289! TXA
.%290! RTS
.%291!
├ONVERT THE GIVEN LOGICAL BLOCK NUMBER TO THE CORRESPONDING PHYSICAL CYLINDER,
SIDE, AND SECTOR NUMBERS. ╘HIS ROUTINE FOLLOWS THE FORMULAE GIVEN EARLIER
WITH A FEW SIMPLIFYING TRICKS.
.%292! CONVERT╠OGICAL┬LOCK╬UM = * ;( .┴┘=BLOCK╬UM ) : .┴=CYL, .╪=SIDE, .┘=SEC
.%293! JSR DIVIDE┬Y18
.%294! LDX #0
.%295! CPY #9
.%296! BCC +
.%297! PHA
.%298! TYA
.%299! SBC #9
.%300! TAY
.%301! PLA
.%302! LDX #1
.%303! + INY
.%304! RTS
.%305!
├OPY A SEQUENTIAL GROUP OF LOGICAL SECTORS INTO MEMORY. ╘HIS ROUTINE IS USED
BY THE DIRECTORY LOADING ROUTINE TO LOAD THE ╞┴╘ AND ╥OOT ─IRECTORY, AND IS
USED BY THE CLUSTER READING ROUTINE TO RETRIEVE ALL OF THE BLOCKS OF A
CLUSTER. ┴FTER THE GIVEN STARTING LOGICAL SECTOR NUMBER IS CONVERTED INTO ITS
PHYSICAL CYLINDER, SIDE, AND SECTOR EQUIVALENT, THE PHYSICAL VALUES ARE
INCREMENTED TO GET THE ADDRESS OF SUCCESSIVE SECTORS OF THE GROUP. ╘HIS
AVOIDS THE OVERHEAD OF THE LOGICAL TO PHYSICAL CONVERSION. ╤UITE A NUMBER OF
TEMPORARIES ARE NEEDED.
.%306! DEST╨TR = 6
.%307! CUR├YLINDER = 8
.%308! CUR╙IDE = 9
.%309! CUR╙ECTOR = 10
.%310! BLOCK├OUNTDOWN = 11
.%311! SOURCE╨TR = 12
.%312!
.%313! COPY┬LOCKS = * ;( .┴┘=START┬LOCK, .╪=BLOCK├OUNT, ($6)=DEST ) : .├╙=ERR
.%314! STX BLOCK├OUNTDOWN
.%315! JSR CONVERT╠OGICAL┬LOCK╬UM
.%316! STA CUR├YLINDER
.%317! STX CUR╙IDE
.%318! STY CUR╙ECTOR
.%319!
.%320! COPY┬LOCK╠OOP = *
.%321! LDA CUR├YLINDER
.%322! LDX CUR╙IDE
.%323! LDY CUR╙ECTOR
.%324! JSR READ┬LOCK
.%325! BCC +
.%326! RTS
.%327! + STA SOURCE╨TR
.%328! STY SOURCE╨TR+1
.%329! LDX #2
.%330! LDY #0
╚ERE ╔ UNROLL THE COPYING LOOP A LITTLE BIT TO CUT THE OVERHEAD OF THE BRANCH
INSTRUCTION IN HALF. (┴ CYCLE SAVED... YOU KNOW).
.%331! - LDA (SOURCE╨TR),Y
.%332! STA (DEST╨TR),Y
.%333! INY
.%334! LDA (SOURCE╨TR),Y
.%335! STA (DEST╨TR),Y
.%336! INY
.%337! BNE -
.%338! INC SOURCE╨TR+1
.%339! INC DEST╨TR+1
.%340! DEX
.%341! BNE -
╔NCREMENT THE CYLINDER, SIDE, SECTOR VALUES.
.%342! INC CUR╙ECTOR
.%343! LDA CUR╙ECTOR
.%344! CMP #10
.%345! BCC +
.%346! LDA #1
.%347! STA CUR╙ECTOR
.%348! INC CUR╙IDE
.%349! LDA CUR╙IDE
.%350! CMP #2
.%351! BCC +
.%352! LDA #0
.%353! STA CUR╙IDE
.%354! INC CUR├YLINDER
.%355! + DEC BLOCK├OUNTDOWN
.%356! BNE COPY┬LOCK╠OOP
.%357! CLC
.%358! RTS
.%359!
╥EAD A CLUSTER INTO THE ├LUSTER ┬UFFER, GIVEN THE CLUSTER NUMBER. ╘HE CLUSTER
NUMBER IS CONVERTED TO A LOGICAL SECTOR NUMBER AND THEN THE SECTOR COPYING
ROUTINE IS CALLED. ╘HE FORMULA GIVEN EARLIER IS USED FOR THE CONVERSION.
.%360! READ├LUSTER = * ;( .┴┘=CLUSTER╬UMBER ) : CLUSTER┬UF, .├╙=ERR
.%361! ;** CONVERT CLUSTER NUMBER TO LOGICAL BLOCK NUMBER
.%362! SEC
.%363! SBC #2
.%364! BCS +
.%365! DEY
.%366! + LDX CLUSTER┬LOCK├OUNT
.%367! CPX #1
.%368! BEQ +
.%369! ASL
.%370! STY 7
.%371! ROL 7
.%372! LDY 7
.%373! + CLC
.%374! ADC FIRST╞ILE┬LOCK
.%375! BCC +
.%376! INY
.%377!
.%378! ;** READ LOGICAL BLOCKS COMPRISING CLUSTER
.%379! + LDX #<CLUSTER┬UF
.%380! STX 6
.%381! LDX #>CLUSTER┬UF
.%382! STX 7
.%383! LDX CLUSTER┬LOCK├OUNT
.%384! JMP COPY┬LOCKS
.%385!
╘HIS NEXT LEVEL OF ROUTINES DEAL WITH THE DATA STRUCTURES OF THE ═╙-─╧╙ DISK
FORMAT.
.%386! ;====═╙-─╧╙ FORMAT LEVEL====
.%387!
.%388! BOOT┬LOCK = 2
.%389!
╥EAD THE DISK FORMAT PARAMETERS, DIRECTORY, AND ╞┴╘ INTO MEMORY.
.%390! LOAD─IRECTORY = * ;( ) : .┴┘=DIRBUF, .╪=DIR┼NTRIES, .├╙=ERR
.%391! LDA #$0E
.%392! STA $FF00
.%393!
╥EAD THE BOOT SECTOR AND EXTRACT THE PARAMETERS.
.%394! ;** GET PARAMETERS FROM BOOT SECTOR
.%395! LDA #0
.%396! LDY #0
.%397! JSR CONVERT╠OGICAL┬LOCK╬UM
.%398! JSR READ┬LOCK
.%399! BCC +
.%400! RTS
.%401! + STA BOOT┬LOCK
.%402! STY BOOT┬LOCK+1
.%403! LDY #13 ;GET CLUSTER SIZE
.%404! LDA (BOOT┬LOCK),Y
.%405! STA CLUSTER┬LOCK├OUNT
.%406! CMP #3
.%407! BCC +
.%408!
╔F A DISK PARAMETER IS FOUND TO EXCEED THE LIMITS OF ╠╥╥, ERROR CODE #60 IS
RETURNED.
.%409! INVALID╨ARMS = *
.%410! LDA #60
.%411! STA ERRNO
.%412! SEC
.%413! RTS
.%414!
.%415! + LDY #16 ;CHECK ╞┴╘ REPLICATION COUNT, MUST BE 2
.%416! LDA (BOOT┬LOCK),Y
.%417! CMP #2
.%418! BNE INVALID╨ARMS
.%419! LDY #22 ;GET ╞┴╘ SIZE IN SECTORS
.%420! LDA (BOOT┬LOCK),Y
.%421! STA FAT┬LOCKS
.%422! CMP #4
.%423! BCS INVALID╨ARMS
.%424! LDY #17 ;GET DIRECTORY SIZE
.%425! LDA (BOOT┬LOCK),Y
.%426! STA ROOT─IR┼NTRIES
.%427! CMP #129
.%428! BCS INVALID╨ARMS
.%429! LSR
.%430! LSR
.%431! LSR
.%432! LSR
.%433! STA ROOT─IR┬LOCKS
.%434! LDY #19 ;GET TOTAL SECTOR COUNT
.%435! LDA (BOOT┬LOCK),Y
.%436! STA TOTAL╙ECTORS
.%437! INY
.%438! LDA (BOOT┬LOCK),Y
.%439! STA TOTAL╙ECTORS+1
.%440! LDY #24 ;CHECK SECTORS PER TRACK, MUST BE 9
.%441! LDA (BOOT┬LOCK),Y
.%442! CMP #9
.%443! BNE INVALID╨ARMS
.%444! LDY #26
.%445! LDA (BOOT┬LOCK),Y
.%446! CMP #2 ;CHECK NUMBER OF SIDES, MUST BE 2
.%447! BNE INVALID╨ARMS
.%448! LDY #14 ;CHECK NUMBER OF BOOT SECTORS, MUST BE 1
.%449! LDA (BOOT┬LOCK),Y
.%450! CMP #1
.%451! BNE INVALID╨ARMS
.%452!
├ALCULATE THE DERIVED PARAMETERS.
.%453! ;** GET DERIVED PARAMETERS
.%454! LDA FAT┬LOCKS ;FIRST ROOT DIRECTORY SECTOR
.%455! ASL
.%456! CLC
.%457! ADC #1
.%458! STA FIRST╥OOT─IR┬LOCK
.%459! CLC ;FIRST FILE SECTOR
.%460! ADC ROOT─IR┬LOCKS
.%461! STA FIRST╞ILE┬LOCK
.%462! LDA TOTAL╙ECTORS ;NUMBER OF FILE CLUSTERS
.%463! LDY TOTAL╙ECTORS+1
.%464! SEC
.%465! SBC FIRST╞ILE┬LOCK
.%466! BCS +
.%467! DEY
.%468! + STA FILE├LUSTER├OUNT
.%469! STY FILE├LUSTER├OUNT+1
.%470! LDA CLUSTER┬LOCK├OUNT
.%471! CMP #2
.%472! BNE +
.%473! LSR FILE├LUSTER├OUNT+1
.%474! ROR FILE├LUSTER├OUNT
.%475!
╟EE, ╔ HAVE MORE COMMENTS EMBEDDED IN THE CODE THAN ╔ DID LAST ISSUE.
.%476! ;** LOAD ╞┴╘
.%477! + LDA #<FATBUF
.%478! LDY #>FATBUF
.%479! STA 6
.%480! STY 7
.%481! LDA #1
.%482! LDY #0
.%483! LDX FAT┬LOCKS
.%484! JSR COPY┬LOCKS
.%485! BCC +
.%486! RTS
.%487!
.%488! ;** LOAD ACTUAL DIRECTORY
.%489! + LDA #<DIRBUF
.%490! LDY #>DIRBUF
.%491! STA 6
.%492! STY 7
.%493! LDA FIRST╥OOT─IR┬LOCK
.%494! LDY #0
.%495! LDX ROOT─IR┬LOCKS
.%496! JSR COPY┬LOCKS
.%497! BCC +
.%498! RTS
.%499! + LDA #<DIRBUF
.%500! LDY #>DIRBUF
.%501! LDX ROOT─IR┼NTRIES
.%502! CLC
.%503! RTS
.%504!
╘HIS ROUTINE LOCATES THE GIVEN ╞┴╘ TABLE ENTRY NUMBER AND RETURNS THE VALUE
STORED IN IT. ╙OME WORK IS NEEDED TO DEAL WITH THE 12-BIT COMPRESSED DATA
STRUCTURE.
.%505! ENTRY┴DDR = 2
.%506! ENTRY╫ORK = 4
.%507! ENTRY┬ITS = 5
.%508! ENTRY─ATA0 = 6
.%509! ENTRY─ATA1 = 7
.%510! ENTRY─ATA2 = 8
.%511!
.%512! GET╞AT┼NTRY = * ;( .┴┘=FAT┼NTRY╬UMBER ) : .┴┘=FAT┼NTRY╓ALUE
.%513! STA ENTRY┬ITS
─IVIDE THE ╞┴╘ ENTRY NUMBER BY TWO AND MULTIPLY BY THREE BECAUSE TWO ╞┴╘
ENTRIES ARE STORED IN THREE BYTES. ╘HEN ADD THE ╞┴╘ BASE ADDRESS AND WE HAVE
THE ADDRESS OF THE THREE BYTES THAT CONTAIN THE ╞┴╘ ENTRY WE ARE INTERESTED
IN. ╔ RETRIEVE THE THREE BYTES INTO ZERO-PAGE MEMORY FOR EASY MANIPULATION.
.%514! ;** DIVIDE BY TWO
.%515! STY ENTRY┴DDR+1
.%516! LSR ENTRY┴DDR+1
.%517! ROR
.%518!
.%519! ;** TIMES THREE
.%520! STA ENTRY╫ORK
.%521! LDX ENTRY┴DDR+1
.%522! ASL
.%523! ROL ENTRY┴DDR+1
.%524! CLC
.%525! ADC ENTRY╫ORK
.%526! STA ENTRY┴DDR
.%527! TXA
.%528! ADC ENTRY┴DDR+1
.%529! STA ENTRY┴DDR+1
.%530!
.%531! ;** ADD BASE, GET DATA
.%532! CLC
.%533! LDA ENTRY┴DDR
.%534! ADC #<FATBUF
.%535! STA ENTRY┴DDR
.%536! LDA ENTRY┴DDR+1
.%537! ADC #>FATBUF
.%538! STA ENTRY┴DDR+1
.%539! LDY #2
.%540! - LDA (ENTRY┴DDR),Y
.%541! STA ENTRY─ATA0,Y
.%542! DEY
.%543! BPL -
.%544! LDA ENTRY┬ITS
.%545! AND #1
.%546! BNE +
.%547!
╔F THE ORIGINAL GIVEN ╞┴╘ ENTRY NUMBER IS EVEN, THEN WE WANT THE FIRST 12-BIT
COMPRESSED FIELD. ╘HE NYBBLES ARE EXTRACTED ACCORDING TO THE DIAGRAM SHOWN
EARLIER.
.%548! ;** CASE 1: FIRST 12-BIT CLUSTER
.%549! LDA ENTRY─ATA1
.%550! AND #$0F
.%551! TAY
.%552! LDA ENTRY─ATA0
.%553! RTS
.%554!
╧THERWISE, WE WANT THE SECOND 12-BIT FIELD.
.%555! ;** CASE 2: SECOND 12-BIT CLUSTER
.%556! + LDA ENTRY─ATA1
.%557! LDX #4
.%558! - LSR ENTRY─ATA2
.%559! ROR
.%560! DEX
.%561! BNE -
.%562! LDY ENTRY─ATA2
.%563! RTS
.%564!
╞INALLY, THIS IS THE FILE COPYING LEVEL. ╔T DEALS WITH READING THE CLUSTERS
OF ═╙-─╧╙ FILES AND COPYING THE DATA THEY CONTAIN TO THE ALREADY-OPEN ├┬═
╦ERNAL FILE, POSSIBLY WITH ┴╙├╔╔-TO-╨┼╘╙├╔╔ TRANSLATION.
.%565! ;====FILE COPY LEVEL====
.%566!
.%567! TRANS═ODE = 14
.%568! LFN = 15
.%569! CBM─ATA╨TR = $60
.%570! CBM─ATA╠EN = $62
.%571! CLUSTER = $64
.%572!
├OPY THE GIVEN CLUSTER TO THE ├┬═ OUTPUT FILE. ╘HIS ROUTINE FETCHES THE NEXT
CLUSTER OF THE FILE FOR THE NEXT TIME THIS ROUTINE IS CALLED, AND IF IT HITS
THE ╬╒╠╠ POINTER OF THE LAST CLUSTER OF A FILE, IT ADJUSTS THE NUMBER OF VALID
FILE DATA BYTES THE CURRENT CLUSTER CONTAINS TO ╞ILE╠ENGTH % ├LUSTER╠ENGTH
(SEE NOTE BELOW).
.%573! COPY╞ILE├LUSTER = * ;( CLUSTER, LFN, TRANS═ODE ) : .├╙=ERR
╥EAD THE CLUSTER AND SETUP TO COPY THE WHOLE CLUSTER TO THE ├┬═ FILE.
.%574! LDA CLUSTER
.%575! LDY CLUSTER+1
.%576! JSR READ├LUSTER
.%577! BCC +
.%578! RTS
.%579! + LDA #<CLUSTER┬UF
.%580! LDY #>CLUSTER┬UF
.%581! STA CBM─ATA╨TR
.%582! STY CBM─ATA╨TR+1
.%583! LDA #0
.%584! STA CBM─ATA╠EN
.%585! LDA CLUSTER┬LOCK├OUNT
.%586! ASL
.%587! STA CBM─ATA╠EN+1
.%588!
╞ETCH THE NEXT CLUSTER NUMBER OF THE FILE, AND ADJUST THE CLUSTER DATA LENGTH
FOR THE LAST CLUSTER OF THE FILE.
.%589! ;**GET NEXT CLUSTER
.%590! LDA CLUSTER
.%591! LDY CLUSTER+1
.%592! JSR GET╞AT┼NTRY
.%593! STA CLUSTER
.%594! STY CLUSTER+1
.%595! CMP #$FF
.%596! BNE COPY╞ILE├LUSTER─ATA
.%597! CPY #$0F
.%598! BNE COPY╞ILE├LUSTER─ATA
.%599! LDA LEN═╠
.%600! STA CBM─ATA╠EN
.%601! LDA #$01
.%602! LDX CLUSTER┬LOCK├OUNT
.%603! CPX #1
.%604! BEQ +
.%605! LDA #$03
.%606! + AND LEN═╠+1
╘HE FOLLOWING THREE LINES WERE ADDED IN A LAST MINUTE PANIC AFTER REALIZING
THAT IF ╞ILE╠ENGTH % ├LUSTER╙IZE == 0, THEN THE LAST CLUSTER OF THE FILE
CONTAINS ├LUSTER╙IZE BYTES, NOT ZERO BYTES.
.%000! BNE +
.%000! LDX LEN═╠
.%000! BEQ COPY╞ILE├LUSTER─ATA
.%607! + STA CBM─ATA╠EN+1
.%608!
.%609! COPY╞ILE├LUSTER─ATA = *
.%610! JSR COMMIE╧UT
.%611! RTS
.%612!
├OPY THE FILE DATA IN THE ═╙-─╧╙ CLUSTER BUFFER TO THE ├┬═ OUTPUT FILE.
.%613! CBM─ATA╠IMIT = $66
.%614!
.%615! COMMIE╧UT = * ;( CBM─ATA╨TR, CBM─ATA╠EN ) : .├╙=ERR
╔F THE THE LOGICAL FILE NUMBER TO COPY TO IS 0 ("NULL DEVICE"), THEN DON'T
BOTHER COPYING ANYTHING.
.%616! LDX LFN
.%617! BNE +
.%618! CLC
.%619! RTS
╧THERWISE, PREPARE THE LOGICAL FILE NUMBER FOR OUTPUT.
.%620! + JSR KERNEL├HKOUT
.%621! BCC COMMIE╧UT═ORE
.%622! STA ERRNO
.%623! RTS
.%624!
.%625! COMMIE╧UT═ORE = *
╨ROCESS THE CLUSTER DATA IN CHUNKS OF UP TO 255 BYTES OR THE NUMBER OF DATA
BYTES REMAINING IN THE CLUSTER.
.%626! LDA #255
.%627! LDX CBM─ATA╠EN+1
.%628! BNE +
.%629! LDA CBM─ATA╠EN
.%630! + STA CBM─ATA╠IMIT
.%631! LDY #0
.%632! - LDA (CBM─ATA╨TR),Y
.%633! BIT TRANS═ODE
.%634! BPL +
╔F WE HAVE TO TRANSLATE THE CURRENT ┴╙├╔╔ CHARACTER, LOOK UP THE ╨┼╘╙├╔╔ VALUE
IN THE TRANSLATION TABLE AND OUTPUT THAT VALUE. ╔F THE TRANSLATION TABLE
ENTRY VALUE IS $00, THEN DON'T OUTPUT A CHARACTER (FILTER OUT INVALID
CHARACTER CODES).
.%635! TAX
.%636! LDA TRANS┬UF,X
.%637! BEQ COMMIE╬EXT
.%638! + JSR KERNEL├HROUT
.%639! COMMIE╬EXT = *
.%640! INY
.%641! CPY CBM─ATA╠IMIT
.%642! BNE -
.%643!
╔NCREMENT THE CLUSTER BUFFER POINTER AND DECREMENT THE CLUSTER BUFFER CHARACTER
COUNT ACCORDING TO THE NUMBER OF BYTES JUST PROCESSED, AND REPEAT THE ABOVE IF
MORE FILE DATA REMAINS IN THE CURRENT CLUSTER.
.%644! CLC
.%645! LDA CBM─ATA╨TR
.%646! ADC CBM─ATA╠IMIT
.%647! STA CBM─ATA╨TR
.%648! BCC +
.%649! INC CBM─ATA╨TR+1
.%650! + SEC
.%651! LDA CBM─ATA╠EN
.%652! SBC CBM─ATA╠IMIT
.%653! STA CBM─ATA╠EN
.%654! BCS +
.%655! DEC CBM─ATA╠EN+1
.%656! + LDA CBM─ATA╠EN
.%657! ORA CBM─ATA╠EN+1
.%658! BNE COMMIE╧UT═ORE
╔F WE ARE FINISHED WITH THE CLUSTER, THEN CLEAR THE ├┬═ ╦ERNAL OUTPUT CHANNEL.
.%659! JSR KERNEL├LRCHN
.%660! CLC
.%661! RTS
.%662!
╘HE FILE COPYING MAIN ROUTINE. ╙ET UP FOR THE STARTING CLUSTER, AND CALL
THE CLUSTER COPYING ROUTINE UNTIL END-OF-FILE IS REACHED. ├HECKS FOR A
╬╒╠╠ CLUSTER POINTER IN THE DIRECTORY ENTRY TO HANDLE ZERO-LENGTH FILES.
.%663! COPY╞ILE = * ;( START├LUSTER, LEN═╠, .┴=TRANS═ODE, .╪=LFN ) : .├╙=ERR
.%664! LDY #$0E
.%665! STY $FF00
.%666! STA TRANS═ODE
.%667! STX LFN
.%668! LDA START├LUSTER
.%669! LDY START├LUSTER+1
.%670! STA CLUSTER
.%671! STY CLUSTER+1
.%672! JMP +
.%673! - JSR COPY╞ILE├LUSTER
.%674! BCC +
.%675! RTS
.%676! + LDA CLUSTER
.%677! CMP #$FF
.%678! BNE -
.%679! LDA CLUSTER+1
.%680! CMP #$0F
.%681! BNE -
.%682! CLC
.%683! RTS
.%684!
╘HIS IS THE TRANSLATION TABLE USED TO CONVERT FROM ┴╙├╔╔ TO ╨┼╘╙├╔╔. ┘OU CAN
MODIFY IT TO SUIT YOUR NEEDS IF YOU WISH. ╔F YOU CANNOT REASSEMBLE THIS FILE,
THEN YOU CAN SIFT THROUGH THE BINARY FILE AND LOCATE THE TABEL AND CHANGE IT
THERE. ┴N ENTRY OF $00 MEANS THE CORRESPONDING ┴╙├╔╔ CHARACTER WILL NOT BE
TRANSLATED. ┘OU'LL NOTICE THAT ╔ HAVE SET UP TRANSLATIONS FOR THE FOLLOWING
┴╙├╔╔ CONTROL CHARACTERS INTO ╨┼╘╙├╔╔: ┬ACKSPACE, ╘AB, ╠INEFEED (├╥), AND
╞ORMFEED. ╔ ALSO TRANSLATE THE NON-╨┼╘╙├╔╔ CHARACTERS SUCH AS █, ▄, ▐, AND _
ACCORDING TO WHAT THEY PROBABLY WOULD HAVE BEEN IF ├OMMODORE WASN'T SO
CONCERNED WITH THE GRAPHICS CHARACTERS.
.%685! TRANS┬UF = *
.%686! ;0 1 2 3 4 5 6 7 8 9 A B C D E F
.%687! .BYTE $00,$00,$00,$00,$00,$00,$00,$00,$14,$09,$0D,$00,$93,$00,$00,$00 ;0
.%688! .BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;1
.%689! .BYTE $20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$2A,$2B,$2C,$2D,$2E,$2F ;2
.%690! .BYTE $30,$31,$32,$33,$34,$35,$36,$37,$38,$39,$3A,$3B,$3C,$3D,$3E,$3F ;3
.%691! .BYTE $40,$C1,$C2,$C3,$C4,$C5,$C6,$C7,$C8,$C9,$CA,$CB,$CC,$CD,$CE,$CF ;4
.%692! .BYTE $D0,$D1,$D2,$D3,$D4,$D5,$D6,$D7,$D8,$D9,$DA,$5B,$5C,$5D,$5E,$5F ;5
.%693! .BYTE $C0,$41,$42,$43,$44,$45,$46,$47,$48,$49,$4A,$4B,$4C,$4D,$4E,$4F ;6
.%694! .BYTE $50,$51,$52,$53,$54,$55,$56,$57,$58,$59,$5A,$DB,$DC,$DD,$DE,$DF ;7
.%695! .BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;8
.%696! .BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;9
.%697! .BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;A
.%698! .BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;B
.%699! .BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;C
.%700! .BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;D
.%701! .BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;E
.%702! .BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;F
.%703!
╘HIS IS WHERE THE TRACK CACHE, ETC. ARE STORED. ╘HIS SECTION REQUIRES 11╦ OF
STORAGE SPACE BUT DOES NOT INCREASE THE LENGTH OF THE BINARY PROGRAM FILE
SINCE THESE STORAGE AREAS ARE ─┼╞╔╬┼─ RATHER THAN ALLOCATED WITH ".BUF"
DIRECTIVES. ╘HE ╒NIX TERMINOLOGY FOR THIS TYPE OF UNINITIALIZED DATA IS "BSS".
.%704! ;====BSS STORAGE====
.%705!
.%706! BSS = *
.%707! TRACKBUF = BSS
.%708! CLUSTER┬UF = TRACKBUF+4608
.%709! FATBUF = CLUSTER┬UF+1024
.%710! DIRBUF = FATBUF+1536
.%711! END = DIRBUF+4096
5. ╒╙┼╥-╔╬╘┼╥╞┴├┼ ╨╥╧╟╥┴═
╘HIS SECTION PRESENTS THE LISTING OF THE USER-INTERFACE ┬┴╙╔├ PROGRAM. ┘OU
SHOULD BE AWARE THAT YOU CAN EASILY CHANGE SOME OF THE DEFAULTS TO YOUR OWN
PREFERENCES IF YOU WISH. ╘HIS PROGRAM IS NOT LISTED IN THE ".%NNN!" FORMAT
THAT THE ASSEMBLER LISTING IS SINCE YOU CAN RECOVER THIS LISTING FROM THE
UUENCODED BINARY PROGRAM FILE. ╘HIS PROGRAM SHOULD BE A LITTLE EASIER TO
FOLLOW THAN THE ASSEMBLER LISTING SINCE ┬┴╙╔├ IS A SELF-COMMENTING LANGUAGE. :-)
10 REM LITTLE RED READER, BY CRAIG BRUCE, 30-SEP-92, FOR C= HACKING NETMAG
11 :
╘HESE LINES SET UP THE DEFAULT ├┬═-─╧╙ AND ═╙-─╧╙ DEVICE NUMBERS, TAKING CARE
TO DISALLOW THEM TO BE THE SAME DEVICE. ┘OU CAN CHANGE THIS TO YOUR OWN DRIVE
CONFIGURATION.
20 CD=PEEK(186) : REM ** DEFAULT CBM-DOS DRIVE **
25 DV=9:DT=0 : REM ** MS-DOS DRIVE, TYPE (0=1571,255=1581)
26 IF DV=CD THEN DV=8:DT=0 : REM ** ALTERNATE MS-DOS DRIVE
27 :
30 PRINT CHR$(147);"INITIALIZING..." : PRINT
40 BANK0 : PK=DEC("8000")
50 IF PEEK(PK+9)=DEC("CB") AND PEEK(PK+10)=131 THEN 60
55 PRINT"LOADING MACHINE LANGUAGE ROUTINES..." : BLOAD"LRR.BIN",U(CD)
60 POKE PK+16,DV : POKE PK+17,DT : SYS PK
╔ "DIM" THE FOLLOWING VARIABLES BEFORE THE ARRAYS TO AVOID THE OVERHEAD OF
PUSHING THE ARRAYS AROUND WHEN CREATING NEW SCALAR VARIABLES.
70 DIM T,R,B,I,A$,C,DT$,FL$,IL$,X,X$
80 DIM DI$(128),CL(128),SZ(128)
90 IF DT=255 THEN DT$="1581" :ELSE DT$="1571"
100 FL$=CHR$(19)+CHR$(17)+CHR$(17)+CHR$(17)+CHR$(17)
110 IL$=FL$:FORI=1TO19:IL$=IL$+CHR$(17):NEXT
120 GOTO 500
130 :
131 REM ** LOAD MS-DOS DIRECTORY **
140 PRINT"LOADING DIRECTORY..." : PRINT
150 SYS PK : SYS PK+3
160 DL=0
╘HE "RREG" INSTRUCTION RETURNS THE RETURN VALUES OF THE .┴, .╪, .┘, AND .╙
REGISTERS FROM THE LAST "SYS" CALL. ╔ CHECK THE 1-BIT OF THE .╙ REGISTER
(THE ├ARRY FLAG) FOR ERROR RETURNS.
170 RREG BL,DC,BH,S : E=PEEK(PK+15)
180 IF (S AND 1) THEN GOSUB 380 : RETURN
190 PRINT"SCANNING DIRECTORY..." : PRINT
200 DB=BL+256*BH
210 IF DC=0 THEN 360
220 FOR DP=DB TO DB+32*(DC-1) STEP 32
230 IF PEEK(DP)=0 OR PEEK(DP)=229 THEN 350
240 IF PEEK(DP+12) AND 24 THEN 350
250 DL=DL+1
╘HIS NEXT LINE IS WHERE ╔ SET THE DEFAULT SELECTION STATUS, TRANSLATION TYPE,
AND ├┬═ FILE TYPE FOR THE ═╙-─╧╙ FILES. ┘OU CAN CHANGE THESE DEFAULTS SIMPLY
BY OVERTYPING THE STRING IN ( ▄ ▄▄▄ ▄▄▄ ) THE "╓" LOCATIONS.
╓ ╓╓╓ ╓╓╓
260 D$=RIGHT$(" "+STR$(DL),3)+" ASC SEQ " : REM ** DEFAULT SEL/TR/FT **
270 A$="" : FORI=0TO10 : A$=A$+CHR$(PEEK(DP+I)) : NEXT
280 A$=LEFT$(A$,8)+" "+RIGHT$(A$,3)
290 PRINT DL; A$
300 D$=D$+A$+" "
310 CL(DL)=PEEK(DP+26)+256*PEEK(DP+27)
320 SZ=PEEK(DP+28)+256*PEEK(DP+29)+65536*PEEK(DP+30)
330 DI$(DL)=D$+RIGHT$(" "+STR$(SZ),6)
340 SZ(DL)=SZ
350 NEXT DP
360 RETURN
370 :
371 REM ** REPORT MS-DOS DISK ERROR **
380 PRINT CHR$(18);"MS-DOS DISK ERROR #";MID$(STR$(E),2);
390 PRINT " ($";MID$(HEX$(E),3);"), PRESS KEY.";CHR$(146)
400 GETKEY A$ : RETURN
410 :
411 REM ** SCREEN HEADING **
420 PRINTCHR$(147);"MS-DEV=";MID$(STR$(DV),2);" MS-TYPE=";DT$;
430 PRINT" CBM-DEV=";MID$(STR$(CD),2):PRINT
440 RETURN
450 :
451 REM ** SCREEN FOOTING **
460 PRINT IL$;"D=DIRECTORY M=MS-DEV F=CBM-DEV Q=QUIT"
470 PRINT"T=TOGGLE-COLUMN, C=COPY-FILES, +/- PAGE";
480 RETURN
490 :
491 REM ** MAIN ROUTINE **
500 T=1 : C=0
510 R=0
520 GOSUB 420
530 PRINT "NUM S TRN TYP FILENAME EXT LENGTH"
540 PRINT "--- - --- --- -------- --- ------"
550 GOSUB 460
560 B=T+17 : IF B>DL THEN B=DL
570 PRINT FL$;: IF T>DL THEN 590
580 FOR I=T TO B : PRINT DI$(I) : NEXT
590 IF DL=0 THEN PRINT CHR$(18);"<NO FILES>";CHR$(146)
600 IF DL=0 THEN 660
610 PRINT LEFT$(IL$,R+5);CHR$(18);
620 ON C+1 GOTO 630,640,650
630 PRINT SPC(4);MID$(DI$(T+R),5,3) : GOTO 660
640 PRINT SPC(7);MID$(DI$(T+R),8,5) : GOTO 660
650 PRINT SPC(12);MID$(DI$(T+R),13,5) : GOTO 660
660 GETKEY A$
╧H SHI^╚OOT. ╔ SCREWED UP THE FOLLOWING LINE IN THE STRING AFTER THE
"+CHR$(13)+" PART. ┘OU'LL NOTICE THAT ╔ HAVE AVOIDED PUTTING CURSOR CONTROL
CHARACTERS INTO THE STRINGS EVERYWHERE ELSE, BUT ╔ FORGOT TO DO THAT HERE.
╘HE "█STUFF▌" SHOULD BE ├URSOR╒P, ├URSOR─OWN, ├URSOR╠EFT, ├URSOR╥IGHT,
├URSOR╚OME, AND ├URSOR├╠╥ CONTROL CHARACTERS, RESPECTIVELY. ╘HESE CHARACTERS
GIVE THE INDEX FOR THE "ON" STATEMENT BELOW.
670 I=INSTR("DMFTC+-Q "+CHR$(13)+"█STUFF▌",A$)
680 PRINT LEFT$(IL$,R+5);DI$(T+R)
690 IF I=0 THEN 600
700 ONIGOTO760,1050,1110,950,1150,1000,1020,730,860,860,770,790,810,830,850,500
710 STOP
720 :
721 REM ** VARIOUS MENU OPTIONS **
730 PRINT CHR$(147);"HAVE AN AWESOME DAY."
740 END
760 GOSUB 420 : GOSUB 140 : GOTO 500
770 R=R-1 : IF R<0 THEN R=B-T
780 GOTO 600
790 R=R+1 : IF T+R>B THEN R=0
800 GOTO 600
810 C=C-1 : IF C<0 THEN C=2
820 GOTO 600
830 C=C+1 : IF C>2 THEN C=0
840 GOTO 600
850 R=0 : C=0 : GOTO 600
860 IF DL=0 THEN 600
870 X=T+R : ON C+1 GOSUB 890,910,930
880 PRINT LEFT$(IL$,R+5);DI$(X) : GOTO 600
890 IF MID$(DI$(X),6,1)=" " THEN X$="*" :ELSE X$=" "
900 MID$(DI$(X),6,1)=X$ : RETURN
910 IF MID$(DI$(X),9,1)="A" THEN X$="BIN" :ELSE X$="ASC"
920 MID$(DI$(X),9,3)=X$ : RETURN
930 IF MID$(DI$(X),14,1)="S" THEN X$="PRG" :ELSE X$="SEQ"
940 MID$(DI$(X),14,3)=X$ : RETURN
950 IF DL=0 THEN 600
960 FOR X=1 TO DL
970 ON C+1 GOSUB 890,910,930
980 NEXT X
990 GOTO 520
1000 IF B=DL THEN T=1 : GOTO 510
1010 T=T+18 : GOTO 510
1020 IF T=1 THEN T=DL-(DL-INT(DL/18)*18)+1 : GOTO 510
1030 T=T-18 : IF T<1 THEN T=1
1040 GOTO 510
1050 PRINT IL$;CHR$(27);"@";
1060 INPUT"MS-DOS DEVICE NUMBER (8-30)";DV
1061 IF CD=DV THEN PRINT"MS-DOS AND CBM-DOS DEVICES MUST BE DIFFERENT!":GOTO1060
1070 INPUT"MS-DOS DEVICE TYPE (71/81)";X
1080 IF X=8 OR X=81 OR X=1581 THEN DT=255:DT$="1581" :ELSE DT=0:DT$="1571"
1090 POKE PK+16,DV : POKE PK+17,DT : SYS PK
1100 GOTO 520
1110 PRINT IL$;CHR$(27);"@";
1120 INPUT "CBM-DOS DEVICE NUMBER (0-30)";CD
1130 IF CD=DV THEN PRINT"MS-DOS AND CBM-DOS DEVICES MUST BE DIFFERENT!":GOTO1120
1140 GOTO 520
1141 :
1142 REM ** COPY FILES **
1150 PRINT CHR$(147);"COPY FILES":PRINT:PRINT
1160 IF DL=0 THEN FC=0 : GOTO 1190
1170 FC=0 : FOR F=1 TO DL : IF MID$(DI$(F),6,1)="*" THEN GOSUB 1200
1180 NEXT F
1190 PRINT : PRINT"FILES COPIED =";FC;" - PRESS KEY"
1191 GETKEY A$ : GOTO 520
1200 FC=FC+1
1210 X$=MID$(DI$(F),19,8)+"."+MID$(DI$(F),29,3)
1220 CF$="":FORI=1TOLEN(X$):IF MID$(X$,I,1)<>" " THEN CF$=CF$+MID$(X$,I,1)
1230 NEXT
1231 IF RIGHT$(CF$,1)="." THEN CF$=LEFT$(CF$,LEN(CF$)-1)
1232 CF$=CF$+","+MID$(DI$(F),14,1)
1240 PRINT STR$(FC);". ";CHR$(34);CF$;CHR$(34);TAB(20);SZ(F)"BYTES";
1245 PRINT TAB(35);MID$(DI$(F),9,3)
1250 CL=CL(F) : LB=SZ(F) - INT(SZ(F)/65536)*65536
╔ HAD TO USE A ─╧╨┼╬ STATEMENT HERE FOR DISK FILES BECAUSE THE REGULAR ╧╨┼╬
STATMENT DOES NOT REDIRECT THE ─╙ AND ─╙$ PSEUDO-VARIABLES. ┘OU'LL NOTICE
THAT THE NON-DISK ╧╨┼╬ STATMENT BELOW HAS A SECONDARY ADDRESS OF 7. ╘HIS IS
TO PUT THE PRINTER INTO LOWERCASE MODE IF YOU ARE OUTPUTTING DIRECTLY TO IT.
┘OU CAN REPLACE THIS WITH A 5 (OR WHATEVER) IF YOU HAVE A SPECIAL INTERFACE
TO AN ╔┬═-COMPATIBLE PRINTER AND YOU WANT TO PRINT DIRECTLY IN ┴╙├╔╔. ╔N THIS
CASE, YOU WOULD SELECT THE "┬╔╬" TRANSLATION MODE FOR THE FILE YOU ARE ROUTING
DIRECTLY TO THE PRINTER.
1260 IF CD>=8 THEN DOPEN#1,(CF$+",W"),U(CD) :ELSE IF CD<>0 THEN OPEN 1,CD,7
1265 IF CD<8 THEN 1288
1270 IF DS<>63 THEN 1288
1275 X$="Y" : PRINT "FILE EXISTS; OVERWRITE (Y/N)";
1280 CLOSE 1 : INPUT X$ : IF X$="N" THEN FC=FC-1 : RETURN
1285 SCRATCH(CF$),U(CD)
1286 DOPEN#1,(CF$+",W"),U(CD)
1288 IF CD<8 THEN 1320
1300 IF DS<20 THEN 1320
1310 PRINT CHR$(18)+"CBM DISK ERROR: "+DS$ : FC=FC-1 : CLOSE1 : RETURN
1320 POKE PK+19,CL/256 : POKE PK+18,CL-PEEK(PK+19)*256
1330 POKE PK+21,LB/256 : POKE PK+20,LB-PEEK(PK+21)*256
1340 TR=0 : IF MID$(DI$(F),9,1)="A" THEN TR=255
1346 X=1 : IF CD=0 THEN X=0
1350 SYS PK+6,TR,X
1355 RREG X,X,X,S : E=PEEK(PK+15)
1356 IF (S AND 1) THEN GOSUB 380 : FC=FC-1
1360 IF CD<>0 AND CD<8 THEN CLOSE1
1370 IF CD>=8 THEN DCLOSE#1 : IF DS>=20 THEN 1310
1380 RETURN
6. ╒╒┼╬├╧─┼─ ╞╔╠┼╙
╚ERE ARE THE BINARY EXECUTABLES IN UUENCODED FORM. ╘HE ├╥├32S OF THE TWO
FILES ARE AS FOLLOWS:
"LRR.128" 1106058594
"LRR.BIN" 460671650
╘HE "LRR.128" FILE IS THE MAIN ┬┴╙╔├ PROGRAM AND THE "LRR.BIN" FILE CONTAINS
THE MACHINE LANUGAGE DISK-ACCESSING ROUTINES.
[╠╥╥.128 AND ╠╥╥.┬╔╬ ARE INCLUDED IN THIS ARCHIVE. -╥╫]
7. ┬╔┬╠╔╧╟╥┴╨╚┘
╘HE FOLLOWING WORKS WERE CONSULTED IN CREATING THIS ARTICLE:
[1] ╩IM ┬UTTERFIELD, "╩IM ┬UTTERFIELD'S ├OMPLETE ├128 ═EMORY ═AP",
_╘HE_╘RANSACTOR_, ╓OLUME 7, ╔SSUE 01, ╩ULY 1986 (┴ ═UST!).
[2] ├OMMODORE ┬USINESS ═ACHINES, _├OMMODORE_1571_─ISK_─RIVE_╒SER'S_╟UIDE_,
├┬═, 1985.
[3] ╙OME PROGRAM CALLED "MSDOS-TO-128" INCLUDED WITH "CS-DOS" BY
═. ╟-SOMETHING. ╧RIGINALLY PUBLISHED IN ├╧═╨╒╘┼!'S ╟AZZETTE, ╔ THINK.
[4] ├OMMODORE ┬USINESS ═ACHINES, _├OMMODORE_128_╨ROGRAMMER'S_╥EFERENCE_╟UIDE_,
┬ANTAM ┬OOKS, 1986.
[5] _╘HE_╘RANSACTOR_, ╓OLUME 4, ╔SSUE 05 ("╘HE ╥EFERENCE ╔SSUE"), ═AY 1983.
=============================================================================