-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathRman04.asm
729 lines (571 loc) · 13.4 KB
/
Rman04.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
;.OPT
;RMAN04;RNDMAN > Rman04
;.TTL
;Fileserver file RMAN04
.RMAN04
;************ RDGBTS ************
;RDGBTS: Get bytes from file
;Entry: ARGA = func code (9)
;ARGB) = ptr to user info (LS)
;ARGC) = " " " " (MS)
;ARGD = file handle
;ARGE) = buffer address (LS)
;ARGF) = " " (MS)
;ARGG) = no. of bytes (LS)
;ARGH) to be read (MS)
;Exit: ARGA = rc
;ARGB) = no. of bytes actually read (LS)
;ARGC) (MS)
;ARGD = flag: normally zero
;$80 if this read includes
;the last byte OR if it is
;completely outside the file.
;The read is done starting at the current SFP.
;A call of RNDMAN.RDSUBO must be done at the start of each
;external GETBYTES operation, followed by one or more calls
;of RDGBTS.
;*** N.B. Attempting a read partially or
;completely outside the file is not an error
;here. Transfer completely outside file
;will have been deletected in RDSUBO.
;1) Get HANDTB entry from handle
;2) Get RANDTB entry
;3) BTSLFT := file size - SFP (bytes left)
;4) EOFFLG := 0 (end of file flag)
;5) IF transfer size < BTSLFT
;THEN BTSLFT := transfer size
;ELSE EOFFLG := $80 (end-of-file)
;6) BTSXFD := BTSLFT (bytes transferred)
;7) The transfer is done in 3 parts (any of which
;may be null).
;If the start address is not badly aligned on
;a disc block boundary, then STRMAN is called to
;get the required disc block into the cache.
;(It may still be there from the last GETBYTES call).
;The relevant bytes are copied into the buffer.
;We are now aligned to a disc block boundary, so
;can do a direct read by calling DSCMAN, provided
;at least 256 bytes remain to be read.
;The final partial block (if any) is read through
;the cache.
.RDGBTS
{
JSR INITRD;GENPTR := user info; MCNUMB := machine no.
LDY #ARGD
LDA (ARGPTR),Y;A := handle
JSR FNDHND;HNDPTR := HANDTB entry
BNE RDGBTZ;Not found - exit
JSR SETRPT;RTEPTR := RANDTB entry
BNE RDGBTZ;Not found (object not file)
LDY #HTMODE
LDA (HNDPTR),Y;check that file open for reading
AND #READAC
BNE RDGBJA
LDA #RDERRO
BNE RDGBTZ
.RDGBJA
CLC ;CHECK CORRECT LIMIT
JSR RDBLFT;BTSXFD := BTSLFT :=
;min(transfer size, bytes left in file)
;Also sets EOFFLG
JSR RDSBFA;Set RDBFAD
JSR RDGBT1;Read first partial disc block
BNE RDGBTZ;Failed
JSR RDGBT2;Read complete disc blocks in middle
BNE RDGBTZ;Failed
JSR RDGBT3;Read final partial disc block
;BNE RDGBTZ;Failed
;Reading worked OK
;LDA #0
;Exit: error code in A
;Bytes transferred in BTSXFD
.RDGBTZ
PHA ;Save error code
LDY #ARGB;Return bytes tranferred
LDA BTSXFD
STA (ARGPTR),Y;LS byte
INY
LDA BTSXFD + 1
STA (ARGPTR),Y;MS byte
INY
LDA EOFFLG;Return EOF flag
STA (ARGPTR),Y
PLA ;Restore error code
JMP RDEXIT;Exit: RC in A
}
;************ RDPBTS ************
;RDPBTS: Put bytes to file
;Entry: ARGA = func code (10)
;ARGB) = (LS) ptr to user info
;ARGC) = (MS)
;ARGD = file handle
;ARGE) = (LS) buffer address
;ARGF) = (MS)
;ARGG) = (LS) number of bytes to be written
;ARGH) = (MS)
;Exit: ARGA = RC
;The write is done starting from the current SFP.
;The file is extended if necessary.
;A call of RNDMAN.RDSUBO must be done at the
;start of each external PUTBYTES operation,
;followed by one or more calls of RDPBTS.
;1) Get HANDTB entry from handle
;2) Get RANDTB entry
;3) Check open for writing
;4) (abolished)
;5) BTSLFT := file size - SFP (bytes left)
;6) IF transfer size > BTSLFT
;THEN extend file
;BTSLFT := transfer size
;7) BTSXFD := BTSLFT (bytes transferred)
;8) The write is done in 3 parts
;(any of which may be null).
;They are (a) via the cache,
;(b) directly to disc, and
;(c) via the cache, as for RDGBTS (q.v.).
;9) Adjust file HWM
.RDPBTS
{
JSR INITRD;GENPTR := user info; MCNUMB:=machine no.
LDY #ARGD
LDA (ARGPTR),Y;A := handle
JSR FNDHND;HNDPTR := HANDTB entry
BNE RDPBTJ;Not found - exit
JSR SETRPT;RTEPTR := RANDTB entry
BNE RDPBTJ;Not found - exit
LDY #HTMODE;Check file open for update
LDA (HNDPTR),Y;Get mode
AND #WRITAC;Write access
BNE RDPBTA;OK to write
LDA #RDERRN;"Not open for update"
.RDPBTJ
BNE RDPBTZ;Always jumps
.RDPBTA
SEC ;CHECK CORRECT LIMIT
JSR RDBLFT;BTSXFD := BTSLFT :=
;min(transfer size, bytes left in file)
LDA EOFFLG;Get end-of-file flag
BEQ RDPBTB;Not end of file
;Must call MAPMAN to extend file
CLC
LDY #RTCSFP;NEWFSZ := SFP + xfer size
;rounded up modulo 256 (whole block)
LDA (RTEPTR),Y;SFP LS byte
LDY #ARGG
ADC (ARGPTR),Y;xfer size (LS)
STA NEWFSZ
INY
LDA (ARGPTR),Y
LDY #RTCSFP + 1
ADC (RTEPTR),Y
STA NEWFSZ + 1;CS
INY
LDA (RTEPTR),Y
ADC #0
STA NEWFSZ + 2;MS
CLC
LDA #&FF;Add 255 to round up
ADC NEWFSZ;Don't want LS byte
LDA #4;Add extra 1K
ADC NEWFSZ + 1
STA NEWFSZ + 1
BCC RDPBTK
INC NEWFSZ + 2
.RDPBTK
LDA #0
STA NEWFSZ;Clear LS byte
;ADC NEWFSZ + 2
;STA NEWFSZ + 2
JSR RDCHSZ;Extend file
BNE RDPBTZ;Failed
.RDPBTB
LDY #ARGG;BTSLFT := xfer size
LDA (ARGPTR),Y
STA BTSLFT
INY
LDA (ARGPTR),Y
STA BTSLFT + 1
JSR RDSBFA;Set RDBFAD
JSR RDPBT1;Write 1st partial block
BNE RDPBTZ;Failed
JSR RDPBT2;Write complete disc blocks
BNE RDPBTZ;Failed
JSR RDPBT3;Write final partial block
BNE RDPBTZ;Failed
;Writing worked OK
JSR RDSHWM;Adjust file HWM
LDA #0;=> successful return
.RDPBTZ
JMP RDEXIT;EXIT: RC IN A
}
;*** RDBLFT ***
;Initialize BTSLFT, BTSXFD & EOFFLG
;for PUTBYTES/GETBYTES.
;Carry is used as entry condition ** 24/1/84 **
.RDBLFT
{
LDA #0;EOFFLG := 0
STA EOFFLG
LDY #RTFSZE;BTSLFT := filesize - SFP
BCS RDBLF1;C=1 -> use filesize, use HWM
LDY #RTHWM
SEC
.RDBLF1
LDA (RTEPTR),Y;** 24/1/84 **
INY
STY RNDTMP
LDY #RTCSFP
SBC (RTEPTR),Y
STA BTSLFT;LS byte
LDY RNDTMP;** 24/1/84 **
LDA (RTEPTR),Y
LDY #RTCSFP + 1
SBC (RTEPTR),Y
STA BTSLFT + 1;CS Byte
INC RNDTMP;** 24/1/84 **
LDY RNDTMP;next byte
LDA (RTEPTR),Y
LDY #RTCSFP + 2
SBC (RTEPTR),Y;MS byte left in A
BCS RDBLFA;Size >= SFP
;If filesize < SFP set BTSLFT to 0
LDA #0;BTSLFT := 0
STA BTSLFT
STA BTSLFT + 1
;Test xfer size > bytes left
;> if A non-zero (MS byte)
;or if xfer size > BTSLFT
.RDBLFA
BNE RDBLFE;A not 0
SEC ;BTSLFT - xfer size
LDA BTSLFT
LDY #ARGG
SBC (ARGPTR),Y
STA RNDTMP;Store LS byte
LDA BTSLFT + 1
INY
SBC (ARGPTR),Y
ORA RNDTMP;for zero test
BEQ RDBLFB;BTSLFT = xfer size
BCC RDBLFB;BTSLFT < xfer size
;BTSLFT > xfer size: transfer OK
;Set BTSLFT := xfer size
.RDBLFE
LDY #ARGG
LDA (ARGPTR),Y
STA BTSLFT
INY
LDA (ARGPTR),Y
STA BTSLFT + 1
JMP RDBLFC
;BTSLFT < xfer size: transfer too long
;or outside file
;Set EOFFLG to $80
.RDBLFB
LDA #&80
STA EOFFLG
;BTSLFT now says how many bytes can be
;transferred: set BTSXFD to this.
.RDBLFC
LDA BTSLFT
STA BTSXFD
LDA BTSLFT + 1
STA BTSXFD + 1
RTS
}
;*** RDSBFA ***
;Set RDBFAD from call stack
.RDSBFA
LDY #ARGE
LDA (ARGPTR),Y
STA RDBFAD
INY
LDA (ARGPTR),Y
STA RDBFAD + 1
RTS
;*** RDGBT1 ***
;Read the first partial block of a GETBYTES
;transfer, taking the SFP to a disc block
;boundary.
.RDGBT1
{
JSR RDSZE1;Get no. of bytes in A
CMP #0
BEQ RDGB1X;Nothing to do
STA RNDTMP;Save no. of bytes
JSR RDGBLK;Get required block in cache
BNE RDGB1Z;Failed
;Copy from cache buffer to user buffer
LDA RDBFAD;MOVETO := RDBFAD
STA MOVTO
LDA RDBFAD + 1
STA MOVTO + 1
LDY #RTCSFP;Offset in cache blk
LDA (RTEPTR),Y;given by LS byte of SFP
CLC
ADC GENPTR
STA MOVFRM
LDA GENPTR + 1
ADC #0
STA MOVFRM + 1
LDX RNDTMP;No. of bytes to copy
JSR MOVE;Copy
JSR RDADJ1;Adjust BTSLFT, RDBFAD, SFP
.RDGB1X
LDA #0;Empty partial block
.RDGB1Z
RTS
}
;*** RDPBT1 ***
;Write the first partial block of a PUTBYTES
;transfer, taking the SFP to a disc block
;boundary.
.RDPBT1
{
JSR RDSZE1;Get no. of bytes in A
CMP #0
BEQ RDPB1X;Nothing to do
STA RNDTMP;Save no. of bytes
JSR RDGBLK;Get required block in cache
BNE RDPB1Z;Failed
;Copy from user buffer to cache buffer
LDA RDBFAD;MOVFRM := RDBFAD
STA MOVFRM
LDA RDBFAD + 1
STA MOVFRM + 1
LDY #RTCSFP;Offset in cache blk
LDA (RTEPTR),Y;given by LS byte of SFP
CLC
ADC GENPTR
STA MOVTO
LDA GENPTR + 1
ADC #0
STA MOVTO + 1
LDX RNDTMP;No. of bytes to copy
JSR MOVE;Copy
JSR MRKDRT;Mark cache buffer dirty
JSR RDADJ1;Adjust BTSLFT, RDBFAD, SFP
.RDPB1X
LDA #0;Empty partial block
.RDPB1Z
RTS
}
;*** RDSZE1 ***
;Return size of 1st partial block in A.
;size1 := (0 - LS byte of SFP) mod 256
;size := min(size1, BTSLFT)
.RDSZE1
{
LDA #0
SEC
LDY #RTCSFP
SBC (RTEPTR),Y;0 - LS(SFP)
;A := min(A, BTSLFT)
LDX BTSLFT + 1;Is BTSLFT > 256
BNE RDSZEZ
CMP BTSLFT
BCC RDSZEZ;A < BTSLFT
LDA BTSLFT;A > BTSLFT
.RDSZEZ
RTS
}
;*** RDADJ1 ***
;Adjust BTSLFT, RDBFAD, SFP by RNDTMP
.RDADJ1
{
SEC ;BTSLFT -:= RNDTMP
LDA BTSLFT
SBC RNDTMP
STA BTSLFT
BCS RDAJ1K
DEC BTSLFT + 1
.RDAJ1K
CLC ;RDBFAD +:= RNDTMP
LDA RDBFAD
ADC RNDTMP
STA RDBFAD
BCC RDADJ3
INC RDBFAD + 1
}
;RDADJ3 entry adjusts SFP only
.RDADJ3
CLC ;SFP +:= RNDTMP
LDY #RTCSFP
LDA (RTEPTR),Y
ADC RNDTMP
STA (RTEPTR),Y
INY
LDA (RTEPTR),Y
ADC #0
STA (RTEPTR),Y
INY
LDA (RTEPTR),Y
ADC #0
STA (RTEPTR),Y
RTS
;*** RDGBT2 *** and *** RDPBT2 ***
;Do middle part of GETBYTES or PUTBYTES transfer
;i.e. that part consisting of whole disc blocks.
;The code is identical apart from the disc action.
.RDGBT2
LDA #1;DSCMAN.READ
BNE RDBT2A;Always jumps
.RDPBT2
LDA #2;DSCMAN.WRITE - PUTBYTES entry
.RDBT2A
{
STA RNDTMP;Store disc action for later
;Determine how many whole blocks there
;are to be transferred.
;*** Assumes blocksize = 256 bytes ***
LDA BTSLFT + 1;Blocks = ms byte of bytes left
BEQ RDBT2X;Nothing to do
;Must flush all blocks of object from
;cache before doing direct transfer.
JSR RDFALL;Leaves DISC & SIN on NEWARG stack
BNE RDBT2Z;Failed
;Call DSCMAN to READ/WRITE directly from/to
;caller's buffer.
;Start block no. is given by MS
;two bytes of SFP.
LDY #RTCSFP + 1
LDA (RTEPTR),Y;SFP (CS)
LDY #ARGG
STA (NEWARG),Y;Block no. (LS)
LDY #RTCSFP + 2
LDA (RTEPTR),Y;SFP (MS)
LDY #ARGH
STA (NEWARG),Y;Block no. (MS)
;Number of blocks is given by MS
;byte of BTSLFT.
LDA BTSLFT + 1
INY
STA (NEWARG),Y
LDA #0;MS byte of block count
INY ;always zero (in 64K machine)
STA (NEWARG),Y
LDA RDBFAD;Put buffer address on stack
INY
STA (NEWARG),Y
LDA RDBFAD + 1
INY
STA (NEWARG),Y
;Operation code was placed in RNDTMP
;on entry to this routine.
LDA RNDTMP
JSR SETRTN
JSR DSCMAN;*** DSCMAN.READ or DSCMAN.WRITE **
BNE RDBT2Z;Failed
;Must adjust SFP in RANDTB, RDBFAD, and BTSLFT
;*** Assumes blocksize 256 bytes ***
LDA BTSLFT + 1;No. of blocks
LDY #RTCSFP + 1;Add to CS byte of SFP
CLC
ADC (RTEPTR),Y
STA (RTEPTR),Y;Put back
INY
LDA #0
ADC (RTEPTR),Y;Carry to MS byte of SFP
STA (RTEPTR),Y;Put back
;Adjust MS byte of RDBFAD by no. of blocks
LDA BTSLFT + 1;No. of blocks
ADC RDBFAD + 1;MS byte of buffer addr
STA RDBFAD + 1;Put back
;Only a partial block remains, so MS
;byte of BTSLFT is now zero
LDA #0
STA BTSLFT + 1
;JMP RDBT2X;Exit
.RDBT2X
LDA #0;RC
.RDBT2Z
RTS ;No whole blocks in transfer
}
;*** RDGBT3 ***
;Read the last partial block of a GETBYTES
;transfer
.RDGBT3
{
LDA BTSLFT;Get no. of bytes in A
BEQ RDGB3X;Nothing to do
JSR RDGBLK;Get required block in cache
BNE RDGB3Z;Failed
;Copy from cache buffer to user buffer
LDA RDBFAD;MOVTO := RDBFAD
STA MOVTO
LDA RDBFAD + 1
STA MOVTO + 1
LDA GENPTR;MOVFRM := GENPTR
STA MOVFRM
LDA GENPTR + 1
STA MOVFRM + 1
LDX BTSLFT;No. of bytes to copy
STX RNDTMP;Store for RDADJ3 below
JSR MOVE;Copy
JSR RDADJ3;Adjust SFP
.RDGB3X
LDA #0;Empty partial block
.RDGB3Z
RTS
}
;*** RDPBT3 ***
;Write the last partial block of a PUTBYTES
;transfer
.RDPBT3
{
LDA BTSLFT;Get no. of bytes in A
BEQ RDPB3X;Nothing to do
JSR RDGBLK;Get required block in cache
BNE RDPB3Z;Failed
;Copy from user buffer to cache buffer
LDA RDBFAD;MOVFRM := RDBFAD
STA MOVFRM
LDA RDBFAD + 1
STA MOVFRM + 1
LDA GENPTR;MOVTO := GENPTR
STA MOVTO
LDA GENPTR + 1
STA MOVTO + 1
LDX BTSLFT;No. of bytes to copy
STX RNDTMP;For RDADJ3 call below
JSR MOVE;Copy
JSR MRKDRT;Mark cache buffer dirty
JSR RDADJ3;Adjust SFP
.RDPB3X
LDA #0;Empty partial block
.RDPB3Z
RTS
}
;********* RDEOF *****************
;RDEOF: read "end of file" condition
;Entry: ARGA = fn. code (#0F)
;ARGB = ptr. to user info (LS)
;ARGC = ptr. to user info (MS)
;ARGD = handle
;Exit : ARGA = RC
;ARGB = zero if SFP <= HWM
;#FF if SFP => HWM
.RDEOF
{
JSR INITRD
LDY #ARGD
LDA (ARGPTR),Y
JSR FNDHND;Check handle/machine pair
BNE RDEOFZ;Error -> exit
JSR SETRPT;Set Random table ptr. (& check is file)
BNE RDEOFZ;Not a file -> exit
JSR CMPHWP;Compare HWM with PTR
BEQ RDEOFL;Ptr = HWM -> exit w/$FF
LDA #0
BCS RDEOFX;Ptr < HWM -> exit w/zero
.RDEOFL
LDA #&FF
.RDEOFX
LDY #ARGB
STA (ARGPTR),Y;Set result
LDA #0;Set return code
.RDEOFZ
JMP RDEXIT;Return
}
;.LNK
;RMAN05