====== 4d2008-03 Listings ====== ===== example.2.4th ===== GTK+ mit Forth (1) - GTK Stock Viewer, Listing 1: GtkComboBoxText/example.2.4th. \ GtkComboBoxText/example.2.4th needs GtkToplevel needs GtkTable needs GtkLabel Array needs GtkAlignment Array needs GtkComboBoxText needs GtkImageFromStock needs GtkButton needs GSList \ ------------------------------------------------------------------------------ \ csp4th : GtkComboBox Example 2 MM-080311 \ ------------------------------------------------------------------------------ gtk api definitions libgtk import gtk_stock_list_ids ( -- *list ) GtkComboBoxText definitions private vocabulary example.2 self example.2 definitions also gtk api GtkToplevel new window GtkTable new table GtkLabel Array new labels GtkAlignment Array new alignments GtkComboBoxText new combo GtkImage new image GtkButton new button GSList new list :: ( wid data -- ) 2drop gtk main_quit ; 2 20 cb cb.quit :: ( wid data -- ) 2drop combo @ dup if 2dup image from-stock button-size ! button label ! then ; 2 20 cb cb.changed : %label ( -- xopts yopts xpad ypad ) GTK_FILL 0 0 0 ; : %alignment ( -- xopts yopts xpad ypad ) GTK_FILL 0 12 0 ; : viewer ( -- ) " GTK Stock Viewer" window init 12 window border-width ! window resizable off " destroy" cb.quit 0 window signal connect drop table init window add 8 table column-spacing ! 8 table row-spacing ! 3 labels init " Stock Item:" 0 labels of init 0 1 0 1 %label table attach " Image:" 1 labels of init 0 1 1 2 %label table attach " Button:" 2 labels of init 0 1 2 3 %label table attach 3 0 do i labels of xalign right loop 3 alignments init 3 0 do i alignments of init 1 2 i dup 1+ %alignment table attach loop combo init 0 alignments of add " changed" cb.changed 0 combo signal connect drop " ?" image from-stock button-size init 1 alignments of add " ?" button init 2 alignments of add 3 0 do i alignments of xalign left loop gtk_stock_list_ids list init list size dup 1- swap 0 do dup i - list of @ dup zcount combo append free loop drop list free 0 combo activate window show_all ; hide cb.quit hide cb.changed previous viewer term? [IF] ?? [ELSE] gtk main bye [THEN] \ ------------------------------------------------------------------------------ \ Last revision: MM-080803 show all -> show_all , gtk main -> gtk main_quit \ MM-080525 : init -> : viewer ===== all_dow31_source_code.fs ===== Reverse–Engineering–Preventer mit DS2401, ALL950828 V0.06 first release. \ -------------------------------------------------------------- \ history: last revision first ALL 14:07 28AUG95 \ ALL950828 V0.06 first release \ .... \ ALL950112 V0.01 first try \ -------------------------------------------------------------- \ TMEM? DALLAS TOUCHMEMORY ALL 11:53 28AUG95 DECIMAL ASSEMBLER P1.5 EQU $PTM \ define TOUCH-MEM DATA port pin FORTH HEX 33 EQU cTMRD DECIMAL \ 0F or 33 are read commands \ -------------------------------------------------------------- \ TMEM? DALLAS TOUCHMEMORY present? ALL 21:13 14APR96 CODE TMEM? ( -- t=PRESENT ) \ TM present? A,# 4 MOV $PTM CLR \ start of RESET pulse LOW B ,# 250 MOV 1$: B , 1$ DJNZ \ 480..960uSEC->500Tcycles $PTM SETB \ end of RESET pulse HIGH B ,# 6 MOV C CLR \ clear CY = NO_presence 2$: $PTM , 3$ JB \ B: HIGH, leave loop B , 2$ DJNZ \ LOOP for 3360uSEC ACC , 2$ DJNZ \ if DATA stays LOW 9$ SJMP \ STUCK LOW 3$: B ,# 40 MOV \ 60..240uSEC-> 160Tcycles 4$: C,/ $PTM ORL B , 4$ DJNZ \ delay CY=1=PRESENCE detect 9$: A CLR A,# 0 SUBB R1,A MOV APUSH LJMP END-CODE \ -------------------------------------------------------------- \ TM>=1uS ..6T, send CY B ,# 05 MOV 1$: B , 1$ DJNZ \ ..6+2+10=18Tcycles C, $PTM MOV \ read DS_DATA ..20Tcycles B ,# 18 MOV 1$: B , 1$ DJNZ \ 20+2+36=78Tcycles B POP \ =60..120uSEC =tSLOT $PTM SETB \ terminate time slot RET END-PROC CODE TM> ACC A RRC TM> c' NEXT LJMP END-CODE \ -------------------------------------------------------------- \ TMC> ACC B PUSH B ,# 8 MOV \ bit count=8 1$: A RRC TM> c' NEXT LJMP END-CODE : TMRD ( -- c ) 255 TM>ACC R0,A MOV \ -> R0 DPL INC A,@DPTR MOVX R1,A MOV \ crc -> R1 B ,# 8 MOV A,R0 MOV \ B=bit count; A=char 1$: A,R1 XRL A RRC \ CY=char XOR crc.0 A,R1 MOV 2$ JNC \ NC: bit0 was 0 A,# 24 XRL \ 18h feedbacks 2$: A RRC R1,A MOV \ positition new crc A,R0 MOV A RR R0,A MOV \ next bit to bit0 B , 1$ DJNZ \ NZ: more bits A,R1 MOV @DPTR,A MOVX DPL DEC \ put crc' DP=>SP LJMP END-CODE \ -------------------------------------------------------------- \ .tm# TML show DOW/DS2401 data ALL 12:43 31JAN95 \ L. shows low byte as 2 HEX chars : .tm# TMEM? IF CR cTMRD TM> ===== Euler9.fs ===== euler9 .solution ( uho) \ Euler 9 uho 2008-08-24 \ a + b + c = 1000 : a_b_c ( a b -- a b c ) 2dup + 1000 swap - ; \ a^2 + b^2 = c^2 : pytriple? ( a b c -- flag ) >r dup * swap dup * + r> dup * = ; : euler9? ( a b -- flag ) a_b_c pytriple? ; : euler9 ( -- a b c ) 500 dup 1 DO dup I DO J I euler9? IF drop J I a_b_c UNLOOP UNLOOP EXIT THEN LOOP LOOP drop 0 0 0 ; : .solution ( a b c -- ) dup IF >r cr ." a=" over . ." b=" dup . ." c=" r@ . cr ." a+b+c=" 2dup + r@ + . cr ." a*b*c=" * r> * . EXIT THEN drop drop drop cr ." No solution" ; euler9 .solution ===== keep-track-of-time.fs ===== Keeping track of Time; Study timers provided using gforth; Mac OSX (PowerBook G4). \\ And: Brian Fox in 2008, Elapsed timer for gforth compatible with Win32Forth. \ Keeping track of Time \ Study timers provided using gforth - Mac OSX (PowerBook G4) vocabulary test test definitions : runtime-test ( -- ) page 0 3 at-xy ." time t2-t1 max min .s ratio" 0. 0. { D: utime0 D: utime1 } 0. 0. { D: usertime0 D: usertime1 } 0. 0. { D: systime0 D: systime1 } 0. 10000000000. { D: utmax D: utmin } 0. 10000000000. { D: usermax D: usermin } 0. 10000000000. { D: sysmax D: sysmin } begin \ permanent display times utime ( -- dutime ) to utime0 cputime ( -- duser0 dsystem0 ) to systime0 to usertime0 1000000 for ( insert testword here ) next cputime ( -- duser1 dsystem1 ) to systime1 to usertime1 utime ( -- dutime ) to utime1 \ formatted display of times cr 0 0 at-xy ." user: " usertime0 20 ud.r usertime1 usertime0 d- 2dup usermax d> if 2dup to usermax then 2dup usermin d< if 2dup to usermin then 10 ud.r usermax 10 ud.r usermin 10 ud.r space .s usermin d>f usermax d>f f/ f. cr 0 1 at-xy ." sys : " systime0 20 ud.r systime1 systime0 d- 2dup sysmax d> if 2dup to sysmax then 2dup sysmin d< if 2dup to sysmin then 10 ud.r sysmax 10 ud.r sysmin 10 ud.r space .s sysmin d>f sysmax d>f f/ f. cr 0 2 at-xy ." ut : " utime0 20 ud.r utime1 utime0 d- 2dup utmax d> if 2dup to utmax then 2dup utmin d< if 2dup to utmin then 10 ud.r utmax 10 ud.r utmin 10 ud.r space .s utmin d>f utmax d>f f/ f. key? until 0 5 at-xy ; \ Brian Fox in 2008 \ Elapsed timer for gforth compatible with Win32Forth : ms@ ( -- n ) utime drop 1000 / ; 0 value start-time : timer-reset ( -- ) ms@ to start-time ; : .#" ( n1 n2 -- a1 n3 ) >r 0 <# r> 0 ?do # loop #> ; : .elapsed ( -- ) ." Elapsed time: " ms@ start-time - 1000 /mod 60 /mod 60 /mod 2 .#" type ." :" 2 .#" type ." :" 2 .#" type ." ." 3 .#" type ; : elapse ( -- ) timer-reset interpret cr .elapsed ; 0 [if] ----- Gforth 0.6.2, Copyright (C) 1995-2003 Free Software Foundation, Inc. Gforth comes with ABSOLUTELY NO WARRANTY; for details type `license' Type `bye' to exit include elapsed.fs ok ok elapse 5000 ms Elapsed time: 00:00:05.000 ok elapse 10000 ms Elapsed time: 00:00:10.001 ok ----- Brian Fox [then] : .. bye ; words cr cr ===== bootmast.fs ===== Zutaten fuer FAT-Reparatur und Bootmaster unter Turbo-FORTH-83. Auch fuer ZF geeignet. \ **************************************************** \ * * \ * BOOTMAST.FTH * \ * * \ * Zutaten fuer FAT-Reparatur und Bootmaster unter * \ * Turbo-FORTH-83. Auch fuer ZF geeignet. * \ * * \ * Fred Behringer - Forth-Gesellschaft - 8.8.2008 * \ * * \ **************************************************** \ ==================================================== \ Bei Arbeiten mit ZF: \ zf fload bootmast.fth - .fth nicht vergessen! \ attributs off wegnehmen! attributs in ZF unbekannt. \ Ansonsten scheint auch unter ZF alles zu gehen. \ ==================================================== attributs off \ Fuer den Fall, dass kein ANSI.SYS in der CONFIG.SYS ist. \ Bei Arbeiten mit ZF wegnehmen ! hex 210 allot here \ Platz fuer mind. 1 Sektor = 512d Bytes here 0f and - \ sectbuf an Paragraphenanfang 200 - \ Anfang des Sektorpuffers constant sectbuf \ Liefert Adresse des Sektorpuffers \ Sektor lesen: cx = Spur/Sektor-Kombination \ cx = Bits F-0 = FEDCBA98 76543210 : Spur = 76FEDCBA98 : Sektor = 543210 \ = ch cl : 76(cl) &ch : von cl code (getsect) ( seite spur/sektor -- ) ds push \ ds --> es es pop 80 # dl mov \ dl = erste Festplatte cx pop \ Kombination aus Spur (track #) und Sektor ax pop al dh mov \ dh = Seitennummer (head #) sectbuf # bx mov \ bx auf den Anfang des Puffers setzen. 201 # ax mov \ Einen physikalischen Sektor lesen 13 int \ HD-Interrupt aufrufen next end-code \ Sektor schreiben: cx = Spur/Sektor-Kombination (wie unter "Sektor lesen"): \ Spur = ch mit vorangesetzten Bits 7-6 von cl, Sektor = Bits 5-0 von cl code (putsect) ( seite spur/sektor -- ) ds push \ ds --> es es pop 80 # dl mov \ dl = erste Festplatte cx pop \ Kombination aus Spur (track#) und Sektor ax pop al dh mov \ dh = Seitennummer (head #) sectbuf # bx mov \ bx auf den Anfang des Puffers setzen. 301 # ax mov \ Einen physikalischen Sektor schreiben. 13 int \ HD-Interrupt aufrufen next end-code \ 10 Bit Spur und 6 Bit Sektor --> 16 Bit Spur/Sektor \ In dieser Codierung steht es im Master-Boot-Record \ und so wird es in Int 13h, 2/3 in cx verlangt. code sp,sc>spsc ( sp sc -- spsc ) ax pop \ Sektoreingabe 3f # ax and \ Sektor = 6 niederwertige Bits von al bx pop \ Spureingabe 6 # cl mov \ Spur = Bit 6,7 von al vorn an bl bh cl shl \ um 6 Bit nach links bh al or \ Spurbits 6,7 nach Sektorbyte bl ah mov \ Beides in ax sammeln ax push \ und gemeinsam zum Stack next end-code \ Umkehrung von sp,sc>spsc. Weitere Erklaerungen dort. code spsc>sp,sc ( spsc -- sp sc ) ax pop \ Eingabe (und Aufbewahrung in ax) ax bx mov \ der Spur/Sektor-Kombination 6 # cl mov bl cl shr \ um 6 Bit nach rechts bl dh mov \ Spurbits 6,7 nach bits 0,1 von dh ah dl mov \ Spur dx zu 10 Bits ergaenzen dx push \ Spur auf Stack 3f # ax and \ Sektor = 6 niederwertige Bits von al ax push \ Sektor auf Stack next end-code \ MBR lesen und nach sectbuf speichern \ Die Partitionstabelle beginnt bei Adresse 1be. \ Der MBR endet mit den Bytes 55 aa. : getmbr ( -- ) 0 1 (getsect) ; \ Inhalt von sectbuf (gaanz vorsichtig!) in den MBR der Festplatte schreiben. : putmbr ( -- ) 0 1 (putsect) ; \ Sektor-Puffer am Bildschirm anzeigen : showsectbuf ( -- ) sectbuf 200 dump ; \ Nur 100 Bytes anzeigen : showsectbuf100 ( -- ) sectbuf 100 dump ; \ Sektoradresse s-ad (Spur/Sektor-Kombination wie bei (getsect)) des \ n-ten logischen Laufwerks (der erweiterten Partition) auf den Stack \ holen und auch den zugehoerigen Sektor nach sectbuf speichern. Die \ Partitionstabelle beginnt bei Parttab-Offset 1be; ansonsten hat der \ Parttab-Sektor bis auf die beiden Bytes 55 aa am Ende nur Nullen. \ Zur (besser aufbereiteten) Anzeige der Partitionstabelle des logischen \ Laufwerks n kann man (nach entsprechender Um-Interpretation) auch \ (showparttab) verwenden. Man verwechsle die Partitionstabellen der logischen \ Laufwerke der erweiterten Partition nicht mit derem jeweiligen Bootsektor. \ Die Partitionstabellen der logischen Laufwerke entsprechen dem entsprechenden \ (und am selben Platz liegenden) Teil des MBRs (der gesamten Festplatte). : getpart ( n -- s-ad ) \ n = 1 -> 1. logisches Laufwerk, usw. getmbr sectbuf 1b2 + \ Ausgangsposition im Puffer 4 0 \ 4 relevante Zeilen im MBR do 10 + dup c@ 5 = \ Schon erweiterte Partition? if 2 - @ leave then \ Ja, dann s-ad holen und raus. loop \ ( n s-ad(1) ) begin \ k = 0 ... 0 over \ ( n-k s-ad(k+1) 0 s-ad(k+1) ) (getsect) \ ( n-k s-ad(k+1) ) swap 1 - >r \ ( s-ad(k+1) ) sectbuf 1d0 + @ \ ( s-ad(k+1) s-ad(k+2)? ) dup 0= \ ( s-ad(k+1) s-ad(k+2) fl ) if drop 1 \ ( s-ad(k+1) 1 ) else nip 0 \ ( s-ad(k+2) 0 ) then \ ( s-ad(k+?) 0/1 ) r@ \ ( s-ad(k+?) 0/1 n-k-1 ) -rot r> \ ( n-k-1 s-ad(k+?) 0/1 n-k-1 ) 0= \ ( s-ad(k+?) 0/1 fl ) or \ ( s-ad(k+?) fl ) until \ parttab(n) jetzt in sectbuf drop sectbuf 1c0 + @ \ ( fl s-ad(n) ) swap if cr ." Letztes Ext-Laufwerk schon erreicht!" then ; \ Partitionstabelle eines logischen Laufwerks (der erweiterten Partition) aus \ dem Puffer sectbuf holen und an "richtiger Stelle" (nach s-ad) auf die Platte \ zurueckschreiben. s-ad ist derjenige Wert auf dem Stack, der nach Aufruf von \ getpart dort abgelegt wurde. s-ad enthaelt Spur und Sektor in der Codierung \ des Interrupts 13h. Die 0 in putpart entspricht der Seitennummer 0. \ Das Paar n getpart und putpart dient also der Reparatur einer verunglueckten \ Partitionstabelle eines logischen Laufwerks der erweiterten Partition - soweit \ eine solche ueberhaupt vorhanden ist. : putpart ( s-ad -- ) 0 swap (putsect) ; \ Aeusserste Vorsicht ! \ Bootsektor des logischen Laufwerks n (1 = erstes Laufwerk der \ erweiterten Partition usw) holen und in den Sektorpuffer schreiben \ Der Bootsektor des logischen Laufwerks n der erweiterten Partition hat nichts \ mit der Partitionstabelle des logischen Laufwerks zu tun! Voellig falsch waere \ es, sich nach n getboot irgendwelche brauchbaren Daten per (showparttab) \ anzeigen lassen zu wollen (siehe dort). : getboot ( n -- ) getpart 1 swap (getsect) ; \ Partition verstecken. Zunaechst nur in sectbuf (Sektorpuffer). MBR muss \ schon per getmbr in den Puffer geschrieben worden sein. Zum \ Wirksamwerdenlassen dann mit putmbr abschliessen! Vorsicht bei der erweiterten \ Partition! Es ist die Frage, ob ein Verstecken der erweiterten Partition \ sinnvoll ist. Das Verstecken von Partitionen mit zweistelligen \ Dateisystemkennungen wird hier nicht erlaubt. Davon betroffen sind \ insbesondere 82 (Linux swap) und 83 (Linux native). Windows ME auf FAT32-Basis \ hat die Kennung 0C und wird von hidepart voll einbezogen. Windows XP hat (bei \ der ueblichen NTFS-Basis) die Kennung 07 und wird von hidepart ebenfalls voll \ einbezogen. \ Achtung: Es wird bei hidepart, hideall und hideall-ext davon ausgegangen, dass \ Linux, falls vorhanden, in der erweiterten Partition liegt, dass Linux also in \ der Partitionstabelle des MBRs nicht in Erscheinung tritt. Andernfalls wuerde \ der hier verwendete Mechanismus des Versteckens oder Sichtbarmachens nicht \ greifen. Diese Dinge muessen unbedingt noch genauer untersucht werden. \ Alle Operationen spielen sich "nur" im Sektorpuffer sectbuf ab. Sie muessen \ dann noch per putmbr auf die Festplatte geschrieben und durch Neubooten \ des Computers wirksam gemacht werden. : hidepart ( n -- ) \ n wird vorsichtshalber auf [1..4] begrenzt. 1 - 3 and 10 * 1c2 + \ n-1 mal Zeilenverschiebung (10) plus Offset sectbuf + dup dup \ im Puffer (dreimal). c@ f0 and 0= \ Keine Nicht-DOS-Kennung (wie etwa 83 bei Linux) if c@ 0f and 10 or \ Unteres Nibble uebernehmen, 1 in oberes Nibble, swap c! \ Ergebnis nach sectbuf (Sektorpuffer) schreiben; else 2drop \ sonst Kennungsadresse aus dem Puffer wegnehmen. then ; \ Partition sichtbar machen. Zunaechst nur in sectbuf (Sektorpuffer). MBR muss \ schon per getmbr in den Puffer geschrieben sein. Zum Wirksamwerdenlassen \ mit putmbr abschliessen! Vorsicht bei der erweiterten Partition! Weiter wie \ bei hidepart. : unhidepart ( n -- ) \ n wird vorsichtshalber auf [1..4] begrenzt. 1 - 3 and 10 * 1c2 + \ n-1 mal Zeilenverschiebung (10h) plus Offset sectbuf + dup dup \ im Puffer (dreimal). c@ f0 and 10 = \ Keine Nicht-DOS-Kennung (wie etwa 83 bei Linux): if c@ 0f and \ Unteres Nibble uebernehmen, 0 in oberes Nibble, swap c! \ Ergebnis nach sectbuf (Sektorpuffer) schreiben; else 2drop \ sonst Kennungsadresse aus dem Puffer wegnehmen. then ; \ Alle Partitionen, auch die erweiterte, verstecken. Alle Vorsichtsmassnahmen \ von hidepart werden uebernommen. Die Bearbeitung findet nur im Sektorpuffer \ sectbuf statt. Der MBR muss vorher per getmbr dorthin gelegt worden sein. Um \ die Aenderungen auf die Festplatte zu bringen, muss dann noch putmbr \ eingesetzt werden. : hideall ( -- ) 4 0 \ 4 zu bearbeitende Zeilen im MBR do i 1 + hidepart loop ; \ Alle Partitionen, mit Ausnahme der erweiterten, verstecken. Ansonsten alles \ wie bei hideall. : hideall-ext ( -- ) 4 0 \ 4 zu bearbeitende Zeilen im MBR do i 3 and 10 * 1c2 + sectbuf + c@ 0f and \ Erweiterte Partition? 05 <> if i 1 + hidepart \ Nein, dann verstecken else i 1 + unhidepart \ Ja, dann 05 in sectbuf schreiben then loop ; \ Partition bootbar machen. Hat natuerlich fuer die erweiterte Partition \ (normalerweise) keinen Sinn. Zunaechst nur in sectbuf (Sektorpuffer). MBR \ muss schon per getmbr in den Puffer geschrieben worden sein. Zum \ Wirksamwerdenlassen mit putmbr abschliessen! : activatepart ( lw n -- ) \ lw = HD-Laufwerk (1...). Keine Begrenzung! swap 7f + swap \ Jetzt lw = 80... . 1 - 3 and 10 * 1be + \ n = Partition. n-1 begrenzt auf [0...3]. sectbuf + c! ; \ In Partitionstabelle (nach sectbuf) schreiben. \ Partition nicht-bootbar machen. Mit deactivateall (siehe gleich) kann man \ die gesamte Festplatte (welche?) ausschalten. Auch bei Linux? : deactivatepart ( n -- ) \ Byte bei Offset 1be in Partitionstabelle auf 0 -7f swap \ setzen: Also keine Laufwerkangabe noetig !?! activatepart swap ; \ Alle Partitionen auf nicht-bootbar (ID = 00) setzen. Nur im Sektorpuffer \ sectbuf. Der MBR muss vorher in den sectbuf geholt werden. Wenn alle weiteren \ Massnahmen erledigt sind, per putmbr auf der Platte wirksam werden lassen! : deactivateall ( -- ) 4 0 \ 4 zu bearbeitende Zeilen im MBR do i 1 + deactivatepart loop ; \ Die im MBR enthaltene Partitionstabelle mit Erlaeuterungen aus dem im \ Forth-Puffer gespeicherten MBR herausholen und am Bildschirm anzeigen. \ Achtung: (showparttab) kuemmert sich nicht darum, ob im Puffer wirklich ein \ Abbild des momentanen (oder wenigstens eines brauchbaren) MBRs liegt. Vor \ Aufruf von (showparttab) muss man den MBR erst per getmbr von der Festplatte \ in den Puffer holen. Das Forth-Wort showparttab (siehe weiter unten im \ vorliegenden Listing) erledigt beides. \ Eine .com-Datei von etwa demselben Funktionsumfang (mit Erlaeuterungen in \ englischer Sprache) wurde mir am 20.12.2003 von Rolf Schoene \ (Forth-Gesellschaft und damals Institut fuer Angewandte Mathematik der \ TU-Muenchen) uebermittelt. Das Vorliegende praesentiert also das Ganze in \ Forth. Schon allein fuer die ueberaus kompakte Moeglichkeit der Darstellung \ in Forth hat sich der mit diesem Artikel verbundene Aufwand (fuer mich) \ gelohnt. : (showparttab) ( -- ) ." MBR-Partitionstabelle (Kopf 0, Spur 0, Sektor 1, Offset 01BE): " cr cr 05 1 do i 30 + emit ." :" space 10 0 do sectbuf 1be + i + 10 j 1 - * + c@ 0 <# # # #> type space loop cr loop 4 spaces 10 0 do b3 emit 2 spaces loop cr 4 spaces 0c 0 do b3 emit 2 spaces loop c0 emit 03 0 do c4 emit c4 emit c1 emit loop 03 0 do c4 emit loop ." Part.-Laenge (in Sektoren)" cr 4 spaces 08 0 do b3 emit 2 spaces loop c0 emit 03 0 do c4 emit c4 emit c1 emit loop 08 0 do c4 emit loop ." Anzahl vorausgegangener Sektoren" cr 4 spaces 07 0 do b3 emit 2 spaces loop c0 emit 15 0 do c4 emit loop ." Nr des letzten Zylinders (0..7)" cr 4 spaces 06 0 do b3 emit 2 spaces loop c0 emit 09 0 do c4 emit loop ." Nr des letzten Sektors (0..5), Zylinder (6..7)" cr 4 spaces 05 0 do b3 emit 2 spaces loop c0 emit 25 0 do c4 emit loop ." Nr des letzten Kopfes" cr 4 spaces 04 0 do b3 emit 2 spaces loop c0 emit ." 01:FAT12, 04:FAT16<32MB, 05:erw.Part., 06:FAT16>32MB, 07:NTFS" cr 4 spaces 03 0 do b3 emit 2 spaces loop c0 emit 22 0 do c4 emit loop ." Nr des ersten Zylinders (0..7)" cr 4 spaces 02 0 do b3 emit 2 spaces loop c0 emit 16 0 do c4 emit loop ." Nr des ersten Sektors (0..5), Zylinder (6..7)" cr 4 spaces 01 0 do b3 emit 2 spaces loop c0 emit 2b 0 do c4 emit loop ." Nr des ersten Kopfes (0..5)" cr 4 spaces c0 emit 08 0 do c4 emit loop ." 80:aktive Primaerpartition (Bootpartition - nur eine!)," ." 00:inaktiv" cr cr ." Achtung: little endian!" cr ." Die vier Bytes " 04 0 do sectbuf 1ca + i + c@ 0 <# # # #> type space loop ." in Zeile 1 stellen die Hexzahl " 04 0 do sectbuf 1ca + 3 + i - c@ 0 <# # # #> type loop ." dar, usw." cr ; : showparttab ( -- ) \ Kommentare siehe (showparttab) getmbr cr cr (showparttab) ; \ Mit dem Booteinrichtungsprogramm n (bootpart) wird die Partitionstabelle im \ Sektorpuffer sectbuf auf das Booten der Partition n vorbereitet. n wird durch \ "wrapping" auf die Werte 1 bis 4 beschraenkt und stellt die Zeile in der \ Partitionstabelle dar, deren Entsprechung gebootet werden soll. Wird \ irrtuemlich ein Booten von der erweiterten Partition (so man eine eingerichtet \ hat) verlangt, so bricht (bootpart) mit einer Fehlermeldung ab und das System \ wartet auf eine neue Eingabe. Bevor (bootpart) vernuenftig arbeiten kann, muss \ der MBR per getmbr in den Sektorpuffer sectbuf geholt worden sein. Damit die \ Neueinstellungen auf die Festplatte geschrieben werden, muss abschliessend \ putmbr eingesetzt werden. \ Vorsicht mit putmbr, wenn man sich nicht ganz sicher ist, ob man das Resultat \ von getmbr fuer den Fall aller Faelle irgendwo abgespeichert hat! : (bootpart) ( n -- ) \ n = Zeile in der Partitionstabelle dup 1 - 3 and 10 * 1c2 + sectbuf + c@ 0f and 05 = if cr ." Erweiterte Partition" drop exit then hideall-ext \ Alle Partitionen, ausser erweiterter, verstecken. deactivateall \ Alle Laufwerke inaktiv setzen 1 over activatepart \ Laufwerk n in Boot-HD aktiv setzen unhidepart \ Laufwerk n in Boot-HD sichtbar machen (showparttab) ; \ Partitionstabelle anzeigen \ Die vorausgegangenen Vorbereitungsschritte werden ueber bootpart zu einem \ einzigen Schritt zusammengefasst. Die neue Partitionstabelle steht dann im \ MBR der Festplatte. Zum endgueltigen Booten muss der Computer dann neu \ gestartet werden. : bootpart ( n -- ) \ Laufwerk n in Boot-HD endgueltig booten getmbr \ MBR in den Puffer sectbuf holen (bootpart) \ Partitionstabelle vorbereiten putmbr ; \ Puffer sectbuf auf Boot-HD zurueckspeichern \ Glossar \ sectbuf ( -- ad) Konstante, Adresse des Sektorpuffers \ (getsect) ( seite spur/sektor -- ) Sektor von HD nach sectbuf holen \ (putsect) ( seite spur/sektor -- ) Sektor von sectbuf nach HD schreiben \ sp,sc>spsc ( sp sc -- spsc ) Spur und Sektor zu 2 Bytes zusammenfassen \ spsc>sp,sc ( spsc -- sp sc ) Umkehrung von sp,sc>spsc \ getmbr ( -- ) 0 1 (getsect) , MBR von HD nach sectbuf holen \ putmbr ( -- ) 0 1 (putsect) , sectbuf als MBR auf HD schreiben \ showsectbuf ( -- ) sectbuf (200 Bytes) anzeigen - egal, was drin \ showsectbuf100 ( -- ) sectbuf (100 Bytes) anzeigen - egal, was drin \ getpart ( n -- s-ad ) Partitionstabelle n von HD nach sectbuf holen \ putpart ( s-ad -- ) Ergebnis von getpart von sectbuf nach HD schreiben \ getboot ( n -- ) Bootsektor des Laufwerks n von HD nach sectbuf holen \ hidepart ( n -- ) Partition n mit Hi-Nibble 1 versehen - nur im sectbuf \ hideall ( -- ) Alle Partitionen im sectbuf mit Hi-Nibble 1 versehen \ hideall-ext ( -- ) Wie hideall, aber erweiterte Partition mit 05 versehen \ unhidepart ( n -- ) Partition n in sectbuf wieder sichtbar machen \ activatepart ( lw n -- ) HD-ID von Part. n von Platte lw auf 80+lw setzen \ deactivatepart ( n -- ) HD-ID von Partition n auf 00 setzen \ deactivateall ( -- ) HD-ID aller Partitionen auf 00 setzen \ (showparttab) ( -- ) MBR-Partitionstabelle aus sectbuf am Monitor anzeigen \ showparttab ( -- ) Wie (showparttab), aber erst MBR von HD nach sectbuf. \ (bootpart) ( n -- ) sectbuf zum Booten von Partition n vorbereiten \ bootpart ( n -- ) MBR auf der HD zum Booten von Partition n vorbereiten \ Ende des Listings