home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
cpm
/
news
/
cpmnet81.mqr
/
CPMNET81.MAR
Wrap
Text File
|
1985-02-09
|
22KB
|
548 lines
>>>>>>>>>>>>>>>>>>>>> CP/M-Net News <<<<<<<<<<<<<<<<<<<<<<<<
============================================================
Number 3 March, 1981 Volume 1, Issue 3
============================================================
In This Issue
=============
The Famous UP-Arrow Story - Michael J. Karas
CP/M Bit Map File Allocation...EXPLAINED!
A Simple 6 Byte Hexadecimal to ASCII Conversion Routine
A CP/M 1.4 Parameter Display Program in Microsoft Basic
CP/M-Net 'Tip-of-the-Month', 64 character wide DDT or SID
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
The Famous UP-Arrow Story
=========================
by
Michael J. Karas
Some time ago, while working at a job that I would just as
soon forget, the famous up-arrow incident took place. My
desk happened to be right next to that of Kelly Smith,
editor of the CP/M Net (tm) News. Kelly had been spending a
large amount of his time working on a diagnostics software
package for the company's business computer. (The now known
PCC 2000.) Building a diagnostics package can be creative
and on one particular day Kelly wanted to show me how some
of the softare worked. In other words he wanted me to see
some of the creativity that he had put into this software
package.
I went over to his computer setup to look at the CRT screen
while he showed me the Memory Display/Alter routine he had
made. After observing for a short time I asked how do you
back up to the previous memory address if you enter the
wrong data. His response was that you terminated the current
entry sequence and reentered the errored memory address. I
decided that it would be nice if there was a key that would
allow you to simply backup to the previous address.
After lunch, (Kelly usually seemed to pound away at the
keyboard all during lunch in those days;) Kelly asked me if
a newly modified version of his Display Alter Routine solved
my problem. I tried it out and found that while entering
data with the memory display/alter command that use of the
up-arrow (^) key would cause the displayed address to back
up to the previous address. A very useful feature I decided.
Kelly's only comment was that some people get their gibblets
jiggled in the most strange ways. Anyway, to this day the
monitors in all of my personal computers contain a memory
display/alter routine with the up-arrow.
These days I don't usually use the monitors anymore due to
the fact that I have disks and thus access to DDT, Digital
Research's Diagnostic Debugging Tool. The "S" command of DDT
does not have the capability to offer the up-arrow attribute
to ease the pain of putting in the wrong value for a memory
byte. So I took it upon myself to change DDT so that it
would do "Up-Arrow".
If you should desire to "jiggle your giblets" while using
the DDT Version 1.4 debugger package then you will have to
do a little work for the "jigglin'". The rest of this
article describes how to make DDT react to up-arrow.
Operating instructions are at the end of the installation
procedure. Note that this patch is specifically tailored to
DDT Version 1.4 and may not work with other versions. The
short program below should be edited into a file using your
favorite editor with the name "DDTPATCH.ASM". It should then
be assembled into a ".HEX" file using an assembler. Use
particular care to get all of the strange equated numbers at
the beginning exactly right.
;****************************************************************
; PATCH TO GIVE SET MEMORY COMMAND BACKUP CAPABILITY
; IN DDT VERSION 1.4.
;****************************************************************
;
;
WBOOT EQU 00000H ;WARM BOOT ENTRY ADDRESS
BDOS EQU 00005H ;BDOS ENTRY ADDRESS
TPA EQU 00100H ;START OF TRANSIENT PROGRAM
;
;
CMNDLP EQU 06FEH ;LOCATION OF COMMAND LOOP START
;(IN ABSOLUTE DDT IMAGE)
;
DISPLP EQU 0A7EH ;LOCATION OF DISPLAY LOOP START
;(IN ABSOLUTE DDT IMAGE)
;
PATCH EQU 0A91H ;LOCATION OF PATCH IN MEMORY ALTER
;(IN ABSOLUTE DDT IMAGE)
;
ASCHEX EQU 0C53H ;LOCATION OF CONVERSION ROUTINE
;(IN ABSOLUTE DDT IMAGE)
;
ENDDDT EQU 0FD0H ;LOCATION OF END OF DDT 1.4
;(IN ABSOLUTE DDT IMAGE)
;
ORG TPA+1 ;FIX OLD DDT 1.4 MODULE SIZE
;
DW 0FB6H+028H ;NEW MODULE SIZE WITH PATCH
;
ORG PATCH+200H ;OFFSET ASSEMBLY AREA
;
POP H
CALL CHARIN-200H ;GO TO NEW ROUTINE TO GET CHAR
;
CPI 0DH ;IS INPUT CHAR A CARRIAGE RETURN?
JZ INCMADR-200H ;GO TO INCREMENT TO NEXT ADDRESS
;
CPI '.' ;IS INPUT THE EXIT PERIOD?
JZ CMNDLP ;GO BACK TO DDT'S COMMAND LOOP
;
CPI '^' ;IS INPUT AN UPARROW TO BACKUP
JZ DECMADR-200H ;GO TO DECREMENT TO PREV ADDRESS
CALL ASCHEX ;GO TO ASCII TO HEX CONVERSION
RLC ;ADJUST HEX FOR HIGH NIBBLE
RLC
RLC
RLC
MOV D,A ;SAVE HIGH NIBBLE
CALL CHARIN-200H ;GET ASCII FOR LOW CHAR
CALL ASCHEX ;GO TO ASCII TO HEX CONVERSION
ORA D ;COMBINE LOW AND HIGH NIBBLES
NOP ;FIX PATCH SIZE TO FIT IN DDT 1.4
MOV M,A ;PUT NEW VALUE INTO MEMORY
INCMADR:
INX H ;INCREMENT FOR NEXT MEMORY ADDRESS
JMP DISPLP ;GO DISPLAY NEXT MEM ADDRESS
;
;
;CODE TO BE PATCHED IN AT END OF DDT PROGRAM. THESE ROUTINES
;ADD THE CAPABILITY TO GET SINGLE CONSOLE CHARACTERS AND TO
;DECREMENT THE CURRENTLY DISPLAYED MEMORY ADDRESS IN THE DDT
;SET MEMORY COMMAND.
;
ORG ENDDDT+200H
;
CHARIN:
PUSH D ;SAVE POSSIBLE HIGH NIBBLE
PUSH H ;SAVE CURRENT MEMORY ADDRESS
MVI C,01H ;SET BDOS FUNCTION FOR CONIN
CALL BDOS ;USE BDOS FOR CONSOLE INPUT
POP H
POP D
RET
DECMADR:
DCX H ;DECREMENT MEMORY ADDRESS
JMP DISPLP ;GO DISPLAY THE PREVIOUS MEM ADDRESS
;
END
;
;
Once you have made the hex file, then put a copy of it on a
CP/M system disk along with your copy of DDT version 1.4.
Boot up this disk in drive A: and carefully follow the
installation instructions below. If you are not currently
familiar with the operation of DDT now would be a good time
to get the manual out and read it. We will be using DDT to
make a patched version of itself. The sequence below must be
followed exactly. The notation <cr> indicates that you
should enter carriage return. The part of the text that the
system types versus the part that you type should be obvious
if you are familiar with DDT.
A>
A>DDT<cr> <== Invoke DDT
DDT VERS 1.4
-IDDT.COM<cr>
-R<cr> <== Read in a copy of DDT.COM
NEXT PC
1400 0100
-S1308<cr> <== Change bit map for patch
1308 92 88<cr>
1309 08 42<cr>
130A 44 12<cr>
130B 48 02<cr>
130C 40 .<cr>
-F13AC,13B0,00<cr> <== Fill in new zeros to map
-S13B1<cr> <== Add a new bit to map
13B1 00 04<cr>
13B2 00 .<cr>
-M11B6,1400,1A00<cr> <== Move bit map out of way
-IDDTPATCH.HEX<cr>
-R<cr> <== OVerlay DDT.COM with patch
NEXT PC
1400 0000
-M1A00,2000,11DE<cr> <== Move bit map into place
-^C <== Bale out of DDT to System
A>SAVE 19 DDTP.COM<cr> <== Save patched DDT
You are now ready to try out the patched version of DDT.
For the most part DDT will operate just like before. The new
version will modify the way that the "S" substitute memory
command functions. The command is invoked just as before (-
Saaaa<cr> aaaa=desired address). When DDT responds with a
display of the memory address and its contents it will enter
a mode waiting for operator input. Four different things can
be entered at this point:
a) A <cr> may be entered to cause the contents of the next
memory address to be displayed.
b) A "." may be entered to cause DDT to return back to the
command mode. Note that the patched DDT does not need a
<cr> after the "." to return to the command or prompt
mode.
c) A "^" may be entered to cause DDT to display the contents
of the previous memory address. This is the back-up mode.
Note that the backup is immediate and does not require a
<cr> after it.
d) A two digit hexadecimal value may be entered to modify
the contents of the currently displayed memory location.
The digits must be 0-9;A-F or DDT will display a "?" and
return to the prompt mode. The second entered digit will
be taken immediately and will change the memory contents.
The next higher address will then be displayed.
I hope you enjoy the up arrow feature as much as I do. Or
as Kelly Smith would say, "Get your gibblets jiggled."
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
CP/M Bit Map File Allocation...EXPLAINED!
=========================================
by
Kelly Smith
What It's for...
For each diskette "logged-on" to the CP/M Basic Disk
Operating System (BDOS), physical diskette space is
dynamically allocated to that diskette (for later write
operations) and maintained in memory by Bit Mapped
Allocation. When changing diskettes (and to avoid the "R/O"
error message) you must enter Control-C to erase the
previous diskettes Bit Map, and cause the BDOS to read the
file directory to establish the new Bit Map. On subsequent
write operations to the diskette, the Bit Map is modified,
and the diskette File Control Block (FCB) for the (now
closed file) is updated in the File Directory.
What It Is...
The Bit Map is actually a tight encoding of available (or
not) sectors on the diskette. The Bit Map is an array of
single bits which correspond to each block of eight sectors
allocated for usage on the diskette. A blank (formatted)
diskettes Bit Map Allocation array then looks like this:
("Standard" Single Density IBM Format Diskette)
GROUP ALLOCATION MAP DRIVE - B
11000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
000000000000000000
240 GROUPS REMAINING ON DISK OUT OF 243
Notice that two bits are 1's...this predefines allocation
space for the CP/M Directory for the diskette (i.e., 16
sectors or 2 groups), and insures that the directory is not
overwritten when creating new files. All remaining 0's are
free groups, ready to become allocated in the directory.
When the BDOS receives a request to create a file, it first
searches the Bit Map until it finds a bit containing a zero,
and the number (this will be explained shortly) of this bit
is the number of the first free group to be allocated for
the file. The BDOS sets the bit map to a one and places a
one byte hexadecimal group number into the FCB of the
directory, created for the new file. As subsequent write
operations occur for the file, the BDOS examines the last
group number in the FCB (and also the Next Record count) and
from the numbers automatically computes the next physical
track and sector number where the diskette write is to
occur. Keeping in mind that eight sectors equal one group,
when all eight sectors of a group have been written, the
BDOS searches the Bit Map again for the next bit containing
a zero. When a free allocation is found, its group number is
added to the FCB (not necessarily a sequential number) and
the corresponding bit is set to a one. Also note that the
minimum file size that a file will be, is one kilobyte...a
file which has seven or fewer sectors will be shown (by STAT
Filename.Typ<cr>) as utilizing one group (1k); a file which
has eight sectors will be shown as utilizing two groups,
even though the second group is empty.
Here is an example of what one sector of the directory
looks like, showing four FCB's for three files:
Filename.Typ EX RC <--------------Group-------------->
-------------------------------------------------------
MACRO .LIB 00 80 45464748 494A4B4C 4D4E4F50 51525354
MACRO .LIB 01 08 55000000 00000000 00000000 00000000
PLINK .COM 00 0B 56570000 00000000 00000000 00000000
DISKTEST.COM 00 09 58590000 00000000 00000000 00000000
Specifically, note that the file MACRO.LIB has two
entries...and also the Record Count (RC) for the first entry
is set to 80 hexadecimal. As new records are written to the
diskette, the RC is updated by the BDOS. When a transition
occurs from 7F to 80, the BDOS adds a new FCB into the
directory, and also creates a new extension (EX) to the
file. Bit Map allocation then proceeds from the next
available group.
And Why...
As I mentioned, the group allocations may not be sequential
(even though my example shows sequential groups). As files
are deleted from the diskette, they leave "holes" in the Bit
Map to make space available for any new files to be created.
The major advantage here, is that the disk is never required
to be "packed down" (i.e., for iCOM FDOS users or UCSD
Pascal users, you know what I mean!). For users of an
operating system that utilizes Sequential or Linked
Allocation methods, my heart goes out to you...nothing quite
so "gut wrenching" as a disk error in the middle of a pack
operation! The other advantage to Bit Map Allocation, is
true random access to sectors (no "kludge" ISAM, as in MITS
DOS or BASIC and no "rewind file pointers" as in PASCAL),
and dynamic allocation of file size. Another source of
frustration regarding Linked Allocations is when an isolated
sector (which "forward references" the next sector in the
file) is "bombed"...there is no way to recover the ENTIRE
file intact...just up to the point of the offending sector!
Now for some detail (as promised): To determine the group
allocation from the Bit Map, we must first "split" the in
half...then it all begins to make (I hope) good sense. To
find the (hexadecimal) group number of an individual bit in
the Bit Map, take the first digit from the even (or odd)
half row and the digit from the column in the same half. As
shown in the example below then, the next free group
allocation is 02 and the last free group is F1:
GROUP ALLOCATION MAP DRIVE - B
Even Half Row Columns Odd Half Row
0123456789ABCDEF 0123456789ABCDEF
---------------------------------
0 :1100000000000000:0000000000000000: 1
2 :0000000000000000:0000000000000000: 3
4 :0000000000000000:0000000000000000: 5
6 :0000000000000000:0000000000000000: 7
8 :0000000000000000:0000000000000000: 9
A :0000000000000000:0000000000000000: B
C :0000000000000000:0000000000000000: D
E :0000000000000000:00 : F
240 GROUPS REMAINING ON DISK OUT OF 243
The PHYSICAL relationship of sectors to groups is such that
Group 02 starts at Track 2/Sector 20, Group 03 starts at
Track 02/Sector 13 (YES! Sector 13, because of the diskette
"skew factor"...hmmm, a good topic for yet another mundane
article on my part...OK, OK,...BORING!), and so on.
In conclusion, Digital Research's CP/M BDOS makes the most
efficient use of available space on the diskette. Other
operating systems (let's cuss MITS DOS again!) often require
that the file size be specified by the user...overcaution
(and much guessing) results in large amounts of unused
diskette space that is NOT AVAILABLE to other files. This
space can only be recovered by copying the data to a new
diskette with the proper file size specified, and WHATS EVEN
WORSE is that this same procedure must be followed to EXPAND
a file that has already utilized the space originally
allocated to it! So anyway...NICE JOB Dr. Kildall!
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A Simple 6 Byte Hexadecimal to ASCII Conversion Routine
=======================================================
by
Kelly Smith (originator of routine unknown)
Only six bytes of 8080 (or Z80) code can perform a
hexadecimal (0 to F) to ASCII conversion. Assuming that the
hexadecimal digit is in the A register, then:
hex$to$ascii: ; convert low nibble hex digit in the
; the A reg., to ASCII character in the
; A reg.
adi 90h ; first add
daa ; adjust result, if carry
aci 40h ; second add, adjust to ASCII
daa ; adjust result, if carry
.
.
.
How does it work? There are two main considerations for
hexadecimal to ASCII conversion: Is the A register less than
ten, or is the A register greater than or equal to ten?
The first DAA instruction (which operates on the lower four
bits (low nibble)), adjusts the result of the ADI
instruction to less than ten. Then the ACI instruction
operates on the upper four bits (high nibble) by adding the
carry out of the lower nibble. The second DAA instruction
then adjusts the results of the high nibble to less than 10.
If the A register is initially less than ten, the first add
results in 9Xh...in this case, the DAA does not affect the A
register. The second add (with carry) results in 9Xh+40h=DXh
(D Hex = 13 Dec). After the second DAA, the result is 3Xh
where 'X' is the decimal digits 0 through 9; thus the ASCII
representation for decimal digit 9 results in 39
hexadecimal.
If the A register is initially ten or greater, the first
add results in 9Xh (same as before), but the result of the
foqst DAA is 0Yh (i.e., Yh=Xh-10d) and includes the setting
of the carry flag. The next add (with carry) gives us
oYh+40h+1=4Zh, where Z=Y+1. The last DAA has no affect...The
hexadecimal digits 41 to 46 represent the ASCII alphabetics
A to F...for example, let X=10d=Ah, then Y=X-10d=10d-10d=0
and Z=Y+1=0+1=1...the result is 41 hexadecimal, the ASCII
symbol for 'A'...the routine is simpler than the
explanation!
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A CP/M 1.4 Parameter Display Program in Microsoft Basic
=======================================================
by
Kelly Smith (from a program by Rod Hart)
Its not often that you find a really unique utility that
"crosses boundries" between an operating system and a
computer language...this one, is particularly "cute" (and
useful), that I downloaded with XMODEM from Rod Hart's
system...nice job Rod! My only changes were to make it all
fit on a 24 by 80 screen display, without using clear screen
codes that are terminal sensitive. Note also, this WILL NOT
WORK on CP/M 2.2 parameters! So put your "thinking caps" on,
write a version for CP/M 2.2, XMODEM it to Rod or myself and
become FAMOUS (if not rich)!
10 REM CP/M Version 1.4 System Parameter Display Program
20 REM by Roderick W. Hart (WA3MEZ)
30 REM December 23, 1979
40 REM modified February 8, 1981 by Kelly Smith, CP/M-Net
50 PRINT TAB( 10) "Parameters unique to your CP/M Version 1.4 are:"
60 BD=PEEK(7)*256
70 SP=PEEK(BD+&H3A)
80 RB=PEEK(BD+&H3C)
90 LS=PEEK(BD+&H3D)
100 LB=PEEK(BD+&H3E)
110 DL=PEEK(BD+&H3F)
120 DT=PEEK(BD+&H40)
130 RE=PEEK(BD+&H3B)
140 TR=PEEK(BD+&H40)
150 MT=(BD+&H1A)
160 PRINT:PRINT TAB( 10) "Your BDOS starts at ";HEX$(BD);" hex"
180 PRINT TAB( 10) "Your sector map table is located at ";HEX$(MT);" hex"
190 PRINT TAB( 10) "Your directory allocation mask is ";HEX$(DL);" hex"
200 PRINT TAB( 10) "You have";TR;"tracks reserved for the system"
210 PRINT TAB( 10) "You have";SP;"sectors per track"
220 PRINT TAB( 10) "You have";RE;"records per extent"
230 PRINT TAB( 10) "You have";RB;"records per block"
240 PRINT TAB( 10) "Last sector in block is";LS
250 PRINT TAB( 10) "Last block on the disk is";LB
290 PRINT:PRINT TAB( 24);"Sector Map Table"
300 PRINT TAB( 24);"------ --- -----"
310 PRINT
320 FOR X=0 TO (SP-1)
330 MP=PEEK(MT+X)
340 Z=Z+5
350 IF Z<60 THEN 360 ELSE 390
360 PRINT TAB( Z);MP;
370 IF X=(SP-1) THEN 410
380 NEXT X
390 Z=5:PRINT CHR$(15)
400 GOTO 360
410 END
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
CP/M-Net "Tip-of-the-Month"
===========================
by
Kelly Smith and Eddie Currie
Are you one of the "poor unfortunates" that has to contend
with a 64 character wide screen display, and bashes your
head against the CRT in front of you (while mumbeling "why
did I EVER BUY this #`!%&$ THING...it SCREWS UP the DDT
'DUMP' display so badly, I can't even use it!"). Well, no
more tears on the keyboard my friend...just put these
patches into DDT or SID, and as if by magic (at no time do
my fingers leave my hands), VOILA...a 64 character wide
'DUMP' that you can actually READ!!!...follow along:
For users of DDT.COM version 1.4 or 2.2, make the following
substitution...
A>ddt ddt.com<cr> <--- patch DDT.COM using DDT
DDT VER 2.2 <--- DDT announcing itself
NEXT PC
1400 0100 <--- DDT telling us it's used 19 pages
-sa17<cr> <--- Substitute at address 0A17 hex...
0A17 05 08<cr> <--- ...08 instead of 05!
0A18 08 .<cr> <--- end the substitution
-g0<cr> <--- exit DDT and return to CP/M
A>save 19 ddt64.com<cr> <--- save the 64 wide DDT.COM
And for users of SID.COM...
A>sid sid.com<cr> <--- patch SID.COM using SID
SID VER 1.4 <--- SID announcing itself
NEXT PC END
2D00 0100 B3FF <--- SID telling us it's used 44 pages
#saa5<cr> <--- Substitute at address 0AA5 hex...
0AA5 93 96<cr> <--- ...96 instead of 93!
0AA6 08 .<cr> <--- end the substitution
#g0<cr> <--- exit SID and return to CP/M
A>save 44 sid64.com<cr> <--- save the 64 wide SID.COM
What these patches do, is to throw out the space characters
between each display of the hexadecimal representation of
each memory content of the DDT or SID 'DUMP' display...it
crunches the display format, and make it READABLE!
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++