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
|
(* SHard-Patcher fuer Schoenbeck AT-Shard V2.7:
- Vortest/Speichertest
- Keyboard Repeatfrequenz
- Baudrates 19200/38400 werden angeboten
- Refresh-Intervall änderbar (bis zu 5% mehr Leistung)
- control (-3,,,r) liefert im Highbyte das Modemstatusregister (RI etc.)
- control (-5,8,,r) geht in ruc-Bios-Graphikmodus (mit Textausgabe:
Text mit 'out', 'put' etc. schreiben, cursor (x, y) mit y:1..43,
Codes ""4"", ""5"", Scroll löschen jetzt vernünftig (Attribut von 7 auf
0 geändert),
Achtung: getcursor (x, y) im 'begin plot' einbauen.
cursor (x,y) im 'end plot' einbauen, wegen y<25 im Textmodus!)
- Kanal 30 (Archiv 1) jetzt für MF-Laufwerke (5.25" bzw. 3.5"), Default-
Size ist 1.2MB (Achtung bei Formatieren von 3.5"-Floppys!)
- Mit control (-10/-11,...) ("stop", "weiter") wird an den RS232-Kanälen
jetzt nicht nur RTS active/inactive gesetzt sondern auch DTR (Modem).
- An Kanal 32:
Mit control (-3, x, mcr*32+kanal, r) (mcr ist Modemcontrolregister Wert,
x egal) können RTS, DTR explizit gesetzt werden.
- id (6) > 0 : SHard wurde gepatcht.
Michael Staubermann, Version 2: 09.10.87, Keyboardrepeat, Baudrates
Version 3: 04.11.87, Graphikcursor & Graphikmodi
Version 3.1: 20.11.87, >32MB Partitionen f. M+
Version 4: 04.12.87, TX-Interrupt restart
Version 4.1: 10.01.88, Refresh-Intervall änderbar
Version 5: 21.02.88, Kanal 30 1.2MB-Format (3.5")
Version 5.1: 22.02.88,
*)
LET setup channel = 28 ;
LET max partitions = 4 ,
patch version = 5 ,
shard bloecke = 18 ;
patch shard ;
ROW shard bloecke ROW 256 INT VAR block ;
ROW shard bloecke BOOL VAR modified ;
INT VAR old session := 0 ;
REAL VAR partition size := 0.0, partition start 1 := 256.0 * 65536.0 -1.0 ;
INT VAR i ;
FOR i FROM 1 UPTO shard bloecke REP
modified (i) := FALSE
PER ;
ROW 256 INT VAR partition table ;
INT OP & (TEXT CONST hex) :
INT VAR i, h := 0 ;
IF LENGTH hex > 4 THEN errorstop ("OP &: LENGTH > 4") FI ;
FOR i FROM 1 UPTO LENGTH hex REP
rotate (h, 4) ;
INT CONST c :: code (hex SUB i) ;
IF c >= 97 AND c <= 102
THEN h := h OR (c-87)
ELIF c >= 65 AND c <= 70
THEN h := h OR (c-55)
ELIF c >= 48 AND c <= 57
THEN h := h OR (c-48)
ELSE errorstop ("OP &: ungültiges Hexdigit ("+code(c)+")")
FI ;
PER ;
h
ENDOP & ;
TEXT OP % (INT CONST int) :
LET hex = "0123456789ABCDEF" ;
TEXT VAR t := "" ;
INT VAR i, r := int ;
FOR i FROM 1 UPTO 4 REP
rotate (r, 4) ;
t CAT (hex SUB ((r AND 15)+1)) ;
PER ;
t
ENDOP % ;
PROC poke (INT CONST shard adr, INT CONST byte) :
(* Der Shard beginnt bei 1280 d.h. 0500H, EUCONECT bei 504H (='EUMEL') *)
INT VAR block no, block offset ;
IF shard adr < 256
THEN errorstop ("poke: Adresse < 256") ;
LEAVE poke
FI ;
block offset := shard adr-256 ;
rotate (block offset, -1) ;
block offset := (block offset AND 255) + 1 ;
block no := shard adr - 256 ;
rotate (block no, -9) ;
block no := (block no AND 63) + 1 ;
IF block no < 1 OR block no > shard bloecke
THEN errorstop ("poke: falsche Adresse") ;
LEAVE poke
FI ;
TEXT VAR t := " " ;
replace (t, 1, block (block no)(block offset)) ;
replace (t, (shard adr AND 1) + 1, code (byte AND 255)) ;
modified (block no) := TRUE ;
block (block no)(block offset) := t ISUB 1 ;
ENDPROC poke ;
PROC poke2 (INT CONST shard adr, INT CONST word) :
INT VAR r := word ;
poke (shard adr, r) ;
rotate (r, 8) ;
poke (shard adr+1, r) ;
ENDPROC poke2 ;
PROC poken (INT CONST shard adr, TEXT CONST str) :
INT VAR i, adr := shard adr ;
i := 1 ;
WHILE i <= LENGTH str REP
IF (str SUB i+2) = " " OR (str SUB i+2) = ""
THEN poke (adr, &subtext (str, i, i+1)) ;
i INCR 3 ;
adr INCR 1
ELIF (str SUB i+4) = " " OR (str SUB i+4) = ""
THEN poke2 (adr, &subtext (str, i, i+3)) ;
i INCR 5 ;
adr INCR 2
ELSE errorstop ("poken: Zuviele zusammenhängende Bytes")
FI ;
PER ;
ENDPROC poken ;
INT PROC peek (INT CONST shard adr) :
INT VAR block no, block offset ;
block offset := shard adr ;
IF shard adr < 256
THEN errorstop ("peek: Adresse < 256") ;
LEAVE peek WITH 0
FI ;
block offset := shard adr-256 ;
rotate (block offset, -1) ;
block offset := (block offset AND 255) + 1 ;
block no := shard adr-256 ;
rotate (block no, -9) ;
block no := (block no AND 63) + 1 ;
IF block no < 1 OR block no > shard bloecke
THEN errorstop ("peek: falsche Adresse") ;
LEAVE peek WITH 0
FI ;
TEXT VAR t := " " ;
replace (t, 1, block (block no)(block offset)) ;
code (t SUB ((shard adr AND 1) + 1))
ENDPROC peek ;
INT PROC peek2 (INT CONST shard adr) :
INT VAR r := peek (shard adr + 1) ;
rotate (r, 8) ;
r + peek (shard adr)
ENDPROC peek2 ;
PROC get partition :
INT VAR partition, cyls, heads, secs ;
get media size (setup channel, cyls, heads, secs) ;
get partition table ;
get partition number from user ;
line ;
IF (partition size high AND -256) <> 0 OR
(partition start high AND -256) <> 0
THEN errorstop ("Sorry, Partitionsangaben zu hoch")
FI ;
line ;
partition start1 := real24 (partition start high, partition start low)-1.0;
partition size := real24 (partition size high, partition size low) ;
putline ("Platte hat " + text (cyls) + " Cylinder, " + text (heads) +
" Heads, " + text (secs) + " Sektoren = " +
text (real(cyls)*real(heads)*real(secs)/2048.0, 5, 1) + " MB") ;
putline ("Partionsanfang: " +
text ((partition start 1+1.0)/2.0, 6, 0) + " KB = Cylinder " +
text (int ((partition start 1+1.0)/real(secs)/real(heads)))) ;
putline ("Partionsgrösse: " + text (partition size/2.0, 6, 0) + " KB = " +
text (int (partition size/real(secs)/real(heads))) + " Cylinder");
put ("Diese Partition ist") ;
IF NOT partition active
THEN put (""15"nicht"14"")
FI ;
putline ("aktiviert.") ;
line .
get partition table :
blockin (setup channel, partition table, 0.0) .
get partition number from user :
FOR partition FROM 1 UPTO max partitions REP
IF eumel partition CAND yes ("EUMEL-Partiton " +
text (partition type) + " patchen")
THEN LEAVE get partition number from user
FI
PER ;
partition := 0 ;
errorstop ("Keine EUMEL Partition gefunden") .
eumel partition :
partition type >= 69 AND partition type <= 72 .
entry : 216 + partition * 8 .
partition active : bit (partition table (entry), 7) .
partition type : partition table (entry + 2) AND 255 .
partition start low : partition table (entry + 4) .
partition start high: partition table (entry + 5) .
partition size low : partition table (entry + 6) .
partition size high: partition table (entry + 7) .
ENDPROC get partition ;
PROC read shard :
INT VAR i ;
old session := session ;
FOR i FROM 1 UPTO shard bloecke REP
cout (i) ;
modified (i) := FALSE ;
blockin (setup channel, block (i), partition start1 + real(i-1))
PER ;
ENDPROC read shard ;
PROC write shard :
INT VAR i ;
FOR i FROM 1 UPTO shard bloecke REP
IF modified (i)
THEN IF session <> old session
THEN errorstop ("RERUN während patch")
FI ;
blockout (setup channel, block (i), partition start1+real(i-1)) ;
modified (i) := FALSE
FI ;
cout (i)
PER
ENDPROC write shard ;
REAL PROC real24 (INT CONST high, low) :
real (high) * 65536.0 + low real .
low real :
IF low < 0
THEN real (low) + 65536.0
ELSE real (low)
FI
ENDPROC real24 ;
PROC split real24 (REAL CONST r, INT VAR high, low) :
high := int (r/65536.0) ;
low := (code (int (r MOD 256.0)) +
code (int ((r MOD 65536.0)/256.0))) ISUB1
ENDPROC split real24 ;
PROC patch shard :
get partition ;
read shard ;
check if patch possible ;
patch baudrate ;
patch id and mode ;
patch typematic ;
patch refresh ;
patch modem status ;
patch cursor maxima ;
patch attribute bytes ;
patch out restart ;
patch dtr inactive ;
patch mcr set routine ;
patch archive 1 format ;
IF yes ("Änderungen permanent machen")
THEN write shard ;
putline ("Änderungen durchgeführt, System neu booten.") ;
ELSE putline ("Keine Änderungen durchgeführt.") ;
FI .
check if patch possible :
IF peek2 (&"0300") <> &"05EA"
THEN errorstop ("Partition enthaelt keinen SHard")
ELSE IF peek2 (shard ver) <> 7
THEN errorstop ("Dies ist die falsche SHard-Version")
ELIF peek2 (id6) = patch version
THEN putline ("Hinweis: Dieser SHard wurde bereits gepatcht")
ELIF peek2 (id6) <> 0
THEN putline ("Der SHard-Patch wird upgedated")
FI
FI .
shard ver: &"0554" .
mode: &"0556" .
id 6: &"055C" .
patch baudrate :
putline ("Baudrates 50, 75 entfernt, 19200, 38400 eingefügt.") ;
poke2 (&"07E8", 1047) ; (* 3: 110 *)
poke2 (&"07EA", 857) ; (* 4: 134.5 *)
poke2 (&"07EC", 768) ; (* 5: 150 *)
poke2 (&"07EE", 384) ; (* 6: 300 *)
poke2 (&"07F0", 192) ; (* 7: 600 *)
poke2 (&"07F2", 96) ; (* 8: 1200 *)
poke2 (&"07F4", 64) ; (* 9: 1800 *)
poke2 (&"07F6", 48) ; (* 10: 2400 *)
poke2 (&"07F8", 32) ; (* 11: 3600 *)
poke2 (&"07FA", 24) ; (* 12: 4800 *)
poke2 (&"07FC", 16) ; (* 13: 7200 *)
poke2 (&"07FE", 12) ; (* 14: 9600 *)
poke2 (&"0800", 6) ; (* 15: 19200 *)
poke2 (&"0802", 3) ; (* 16: 38400 *)
(* Korrektur der Adressoffsetberechnung auf Baudtable *)
(* Maschinencode nicht veraendern!
08F4:
i8250_baud:
CMP BH,17
JNC i8250_not_ok
CMP BH,3
JC i8250_not_ok
....
0918:
MOV AX,WORD PTR i8250_baud_table-6[BX]
*)
poken (&"08F4", "17 73 75 80 FF 03 72 70") ;
poken (&"0918", "87 E2") .
patch id and mode :
poke2 (id6, patch version) ; (* Update Patch Version *)
IF yes ("Soll ein Vortest durchgeführt werden")
THEN IF yes ("Soll ein Speichertest durchgefuehrt werden")
THEN poke2 (mode, 0)
ELSE poke2 (mode, 256)
FI
ELSE poke2 (mode, 512)
FI .
patch modem status:
poke (&"0A5D", 6) . (* Modem Status Register Offset = 6 *)
patch typematic: (* Nur mit ruc-Bios *)
INT VAR typematic ;
IF yes ("Schneller Keyboardrepeat")
THEN typematic := 4 (* Fast *)
ELSE typematic := 2 * 256 + 12 (* Standard *)
FI ;
(* Maschinencode, nicht veraendern!
0E20:
XOR AX,AX ; Set Default Video Mode
INT 10H
MOV AX,0342 ; Set Typematic + Marwin
MOV BX,typematic ; BH = Delay (0..3), BL = Rate (0..31)
INT 16H
0E2C:
MOV AL,54H ; Ab hier in 'patch refresh'
OUT [43H],AL ;
JMP $+2 ;
MOV AL,interval ; interval = 1.19 * us
OUT [41H],AL ;
RET ; End pc_init
*)
poken (&"0E20", "33 C0 CD 10 B8 42 03 BB " + %typematic + " CD 16 C3") .
(* RET wird ueberschrieben von Refresh *)
patch refresh:
INT VAR refresh ;
TEXT VAR ref := "15.126" ;
line ;
putline ("215us Refresh-Intervall bringen 5% mehr RAM-Performance.") ;
putline ("Achtung: Nicht bei allen RAMs moeglich (z.B. 120ns Toshiba nicht).") ;
put ("RAM-Refresh Intervall (in us):") ;
editget (ref) ; line ;
refresh := int (1.19 * real (ref) + 0.5) ;
IF refresh < 1
THEN refresh := 1
ELIF refresh > 255
THEN refresh := 256
FI ;
put (real (refresh) / 1.19) ;
putline ("us Refresh-Intervall eingestellt.") ;
IF refresh = 256 THEN refresh := 0 FI ;
poken (&"0E2C", "B0 54 E6 43 EB 00 B0 " + subtext (%refresh, 3, 4) +
" E6 41 C3") .
patch cursor maxima:
(* Es werden nur die Maxima bei CURSOR(,) veraendert, CLEOL, CLEOP,SCROLL
etc. arbeiten weiter mit 24 Zeilen, 80 Spalten *)
(* CURSOR y:0..43, x:0..89 EUMEL lässt allerdings nur 0..79 zu *)
poke (&"0EFF", 43) ;
poke (&"0F16", 89) .
patch attribute bytes:
poke (&"0FD4", 0) ; poke (&"0FE8", 0) ; (* CLEOP *)
poke (&"1002", 0) ; (* CLREOL *)
poke (&"1027", 0) . (* SCROLL *)
patch out restart :
poke (&"09BA", 0) . (* out_restart immer: JP $+0 *)
patch dtr inactive :
poke (&"0A30", 8) . (* RTS + DTR inaktiv, OUT2 muss an bleiben *)
patch mcr set routine :
(*
0812: 20 Bytes zur Verfügung
MOV DX,(DI+i8250_base)
ADD DX,i8250_mcr
MOV AL,BH ; Highbyte 2. IOCONTROL Parameter
OUT [DX],AL
MOV CX,0
RET
*)
poken (&"0812", "8B 95 1B 00 83 C2 04 88 F8 EE B9 00 00 C3") .
patch archive 1 format :
line ;
putline ("Archiv-Kanal 30-Laufwerk (bitte Typnummer angeben):") ;
putline (" 0: Nicht vorhanden") ;
putline (" 1: 360K (Standard/Doublestep)") ;
putline (" 2: 720K (Standard/Singlestep)") ;
putline (" 3: 1.2MB (Multifunction)") ;
putline ("ESC: Nichts verändern") ;
put ("Typ:") ;
TEXT VAR t ;
REP inchar (t) UNTIL t >= "0" AND t <= "3" OR t = ""27"" PER ;
putline (t) ;
line ;
IF t = "0" OR t = "1"
THEN poken (&"21DE", "00 01")
ELIF t = "2"
THEN poken (&"21DE", "04 02")
ELIF t = "3"
THEN poken (&"21DE", "01 03")
FI .
ENDPROC patch shard ;
PROC blockin (INT CONST kanal, ROW 256 INT VAR block, REAL CONST blockno) :
INT VAR r, my channel :: channel, high, low ;
split real24 (blockno, high, low) ;
continue (kanal) ;
blockin (block, high AND 255, low, r) ;
continue (my channel) ;
SELECT r OF
CASE 0 :
CASE 1 : errorstop ("Harddisk kann nicht gelesen werden")
CASE 2 : errorstop ("Lesefehler bei Block " + text (blockno))
CASE 3 : errorstop ("Block " + text(blockno) + " zu hoch")
OTHERWISE errorstop ("unbekannter Lesefehler auf Harddisk")
ENDSELECT .
ENDPROC blockin ;
PROC blockout (INT CONST kanal, ROW 256 INT VAR block, REAL CONST blockno):
INT VAR r, my channel :: channel, high, low ;
split real24 (blockno, high, low) ;
continue (kanal) ;
blockout (block, high AND 255, low, r) ;
continue (my channel) ;
SELECT r OF
CASE 0 :
CASE 1 : errorstop ("Harddisk kann nicht beschrieben werden")
CASE 2 : errorstop ("Schreibfehler bei Block " + text (blockno))
CASE 3 : errorstop ("Block " + text (blockno) + " zu hoch")
OTHERWISE errorstop ("unbekannter Schreibfehler auf Harddisk")
ENDSELECT .
ENDPROC blockout ;
PROC get media size (INT CONST kanal, INT VAR cyls, heads, secs) :
INT CONST old channel :: channel ;
continue (kanal) ;
control (-10, 0, 0, cyls) ; cyls INCR 1 ;
control (-11, 0, 0, secs) ;
control (-12, 0, 0, heads) ;
continue (old channel)
ENDPROC get media size ;
(*
PROC dump block (INT CONST adr) :
TEXT VAR t ;
FOR i FROM adr UPTO adr+511 REP
IF (i AND 15) = 0
THEN line ;
put (%i+":") ;
t := "" ;
FI ;
INT CONST j :: peek (i) ;
IF j < 32 OR j > 126 THEN t CAT "."
ELSE t CAT code (j) FI ;
outsubtext (%j, 3, 4) ;
out (" ") ;
IF (i AND 15) = 15
THEN out (t)
FI
PER ;
line
ENDPROC dump block ;
putline ("Partitionstabelle lesen...") ;
get partition ;
putline ("SHard lesen...") ;
read shard ;
put (%peek (1364)) ;
*)
|