← ST-Computer 03 / 1991

ST-Speed: Flexibles Utility, Teil 1

Grundlagen

Utilities - kleine, aber oft sehr hilfreiche Hilfsprogramme, gibt es viele, aber nicht immer sind diese auch brauch- oder leicht erweiterbar (weil z.B. kein Source-Code vorhanden ist). Bei diesem Utility ist beides gewährleistet: leichte Erweiterbarkeit (Assembler-Kenntnisse vorausgesetzt) und nützliche Funktionen für Spieler, Anwender und Programmierer.

Aufgerufen wird ST-Speed mit der Tastenkombination ALT-HELP. Das Utility selber besteht aus zwei Teilen: LADER und HAUPTPROGRAMM. Der Lader sorgt dafür, daß das Hauptprogramm resetresident im Speicher gehalten werden kann. Der Lader ist leider nicht auf meinem eigenen Mist gewachsen (warum sollte man das Rad auch ein zweites Mal erfinden?), sondern wurde [ 1 ] entnommen. Wer genau wissen möchte, wie dieser Lader funktioniert, sollte dort nachlesen. Für uns ist nur wichtig, daß das Hauptprogramm frei verschiebbar im Speicher sein muß.

Den Lader finden Sie im Listing 1. Die Konstante MYMAGIC = $10293847 sorgt dafür, daß das Hauptprogramm ST-SPEED auch nur einmal installiert wird. Im Listing 2 finden Sie den Grundaufbau des Utilities. Sie werden feststellen, daß einige Zeilen noch fehlen, d.h. Sie können zwar schon damit beginnen, das Listing abzutippen (stöhn...), funktionieren wird es aber erst ab Ende des dritten Teils. Am besten warten Sie mit dem Abtippen bis zum dritten Teil, denn wenn Sie einige Funktionen nicht brauchen, z.B. wenn Sie schon Ihre Lieblings-RAM-Disk haben, dann brauchen Sie die entsprechenden Zeilen im Source-Text natürlich nicht mit abzutippen.

Der Aufbau

In den ersten 100 Zeilen finden Sie zunächst einige Makros und Konstantendefinitionen. Jetzt wird es interessant: Es existieren zwei Einsprungadressen, die eine für den Lader, die andere fürs TOS. Ab Zeile 107 (Einsprung vom Lader aus) wird zunächst die Voreinstellung von Diskette geladen. Danach wird ST-SPEED in die VBL-Queue eingetragen, und alle Vektoren, die später verbogen werden, werden nach dem XBRA-Verfahren gesichert.

Die zweite Einsprungadresse (Zeilen 125 ff.) wird vom TOS bei jedem RESET benutzt. Hier sorgt man zunächst dafür, daß der Speicher, den ST-SPEED benutzt, nicht wieder ans GEMDOS zurückgegeben wird (ST-SPEED bleibt somit resident). Danach installiert man alle Vektoren, sofern benötigt (siehe Listing). Soll die RAM-Disk reset-resident sein, wird ab Zeile 164 dafür gesorgt, daß auch dieser Speicherbereich nicht wieder ans GEMDOS zurückgegeben wird. Achtung! Nach einem RESET läßt sich eine installierte Ramdisk nicht mehr aus dem System rausschmeißen. Das liegt daran, daß GEMDOS-Speicherbereiche nicht in beliebiger Reihenfolge wieder freigegeben werden können [2].

Die Hauptroutine

Die Hauptroutine (Zeilen 225 ff.) ist in der VBL-Queue des Rechners verankert und wird alle 1/50, 1/60 oder 1/71 Sekunde (je nach Videomodus) abgearbeitet. Falls der Computer verlangsamt werden soll, wird eine Warteschleife ausgeführt, weiterhin prüft man, ob die Tastenkombination ALT-HELP gedrückt wurde. Wenn dies der Fall war ($4ee.w enthält eine 0), erfolgt die Verzweigung zum Hauptmenü.

Im Hauptmenü findet zunächst eine Überprüfung statt, ob ein Menü überhaupt auf dem Bildschirm angezeigt werden soll. Das ist bei einigen Spielprogrammen erforderlich, da diese Shapes einen Interrupt ausgeben und ein Menü nur den Bildschirmaufbau durcheinander bringen würde.

In der Schleife ab Zeile 256 wird die gedrückte Taste ausgewertet und in ein entsprechendes Unterprogramm verzweigt. Wollen Sie eigene Routinen einfügen, gehen Sie wie folgt vor:

Innerhalb der Schleife fügen Sie die Zeilen

CMPI.B #'x',D0 (x = Kleinbuchstabe oder Zahl) BEQ Unterprogramm

ein. Ein Unterprogramm hat nun folgenden Aufbau:

Falls der Bildschirm vor dem Ausführen der Routine restauriert werden muß und am Ende der Routine nicht zum Hauptmenü zurückgesprungen werden soll, z.B. bei einer Hardcopy-Routine:

Unterprogramm: LEA menueflag(PC),A0 TST.W (A0) BNE.S Up1 BSR hole_screen Up1: <... Ihre Routine ...> BRA ende

Die Routine soll ausgeführt werden, und es soll zum Hauptmenü zurückgesprungen werden.

Unterprogramm: <... Ihre Routine ...> BRA menue

Das Unterprogramm benutzt den oberen Bildschirmbereich, der auch von ST-SPEED benutzt wird (12 Zeilen), für eigene Ausgaben. Das Unterprogramm darf nur ausgeführt werden, wenn auch eine Menüausgabe erfolgen darf.

Unterprogramm: LEA menueflag(PC),A0 TST.W (A0) BNE m_quit BSR loesche_screen <... Ihre Routine ...> BRA menue oder BRA ende

Zu den einzelnen Unterprogrammen in diesem Teil gibt es nicht mehr viel zu sagen, da sie ausreichend gut im Source-Text beschrieben sind.

Im zweiten Teil beschäftigen wir uns mit den RAM-Disk-Routinen, die es u.a. auch erlauben, die RAM-Disk schreibzuschützen. Weiterhin stelle ich Ihnen den XBRA-Lister vor.

[1] Zeitschrift c't, Ausgabe 6/89, „Residenter Wachhund“

[2] Atari-ST Profibuch, H.-D. Jankowski / J.F. Reschke / D. Rabich, Sybex Verlag

Folgende Möglichkeiten bietet ST-Speed

Taste Beschreibung
0-9 den Computer verlangsamen (klappt besonders gut in der mittleren und niedrigen Auflösung). Hiermit werden einige Spielprogramme einfacher zu spielen.
A die Anfangsmeldung ein- und ausschalten (manche Spielprogramme setzen Shapes innerhalb einer Interrupt-Routine auf dem Bildschirm. Damit es zu keinen Kollisionen zwischen ST-SPEED und dem Spielprogramm kommt, kann hiermit die Menümeldung ausgeschaltet werden. Wichtig! Es können jetzt nur noch folgende Funktionen aufgerufen werden: 0-9,A,C,H,P,R,Q,S,L).
B das Boot-Laufwerk ändern. Für alle Festplattenbesitzer besonders interessant, die von beliebigen Partitionen booten möchten (auch von einer reset-residenten RAM-Disk).
C schaltet zwischen 50 und 60 Hertz um.
D Einrichten einer RAM-Disk (auch reset-resident)
I gibt den freien Speicher, Informationen über den Schreibschutzstatus der Laufwerke und die Größe der installierten RAM-Disk aus.
H druckt eine Hardcopy
P Kalt-Start (RESET) (ST-Speed + RAM-Disk werden gelöscht)
Q Utility beenden
R Warmstart (RESET) (ST-Speed + RAM-Disk bleiben im Speicher)
W Hiermit kann man beliebige Laufwerke mit einem Schreibschutz versehen (auch die RAM-Disk).
S speichert aktuelle Informationen über:
- Einschaltmeldung (A)
- Schreibschutz (W)
- Fileprotect (F)
L Lädt gespeicherte Informationen. Die Informationen werden auch beim ersten Programmstart geladen (z.B. bei dem Start aus dem AUTO-Ordner).
X Listet alle im Speicher vorhandenen XBRA-Programme auf (wichtig: Es werden nur Programme angezeigt, die Vektoren im Adreßbereich $8 - $1000 verbiegen).
F Man kann verhindern, daß Programme unerlaubt auf andere zugreifen (Virenschutz). Das ist mit FILEPROTECT möglich. Es gibt zwei Modi: Soft und Hard. Im Soft-Mode werden nur die Betriebssystemfunktionen Fcreate, Fopen (Schreiben und Lesen+Schreiben), Fdelete, im Hard-Mode zusätzlich Fopen (Lesen) und Pexec abgefangen.
* Loader für ST-SPEED V1.x * * Ladeprogramm basiert auf c't - Lösung * Ausgabe 6/89 „Residenter Wachhund" * mymagic: equ $10293847 output \st_speed.tos lea $10000,a0 lea $70000,a1 ht_im0: cmp.l #$12123456,(a0) beq.s hier n_hier: lea 512(a0),a0 cmp.l a1,a0 ble.s ht_im0 bra.s insta hier: cmp.l 4(a0),a0 bne.s n_hier cmp.l #mymagic,12(a0) bne.s n_hier termy: clr.w -(sp) trap #1 insta: move.l #$10000,a0 lea tot_end(pc),a1 inst_g0: cmp.l a0,a1 ble.s inst_g1 lea 512(a0),a0 bra.s inst_g0 inst_g1: move.l a0,a5 lea t_inf(pc),a0 bsr pr_strg clr.w -(sp) pea t_datna(pc) move.w #$3d,-(sp) trap #1 addq.l #8,sp move.w d0,d6 bmi fehler addq.l #2,a5 f1_10: move.w (a5),-2(a5) moveq.l #2,d0 bsr.s fread tst.l d0 bmi fehler cmp.l #$12123456,-2(a5) bne.s f1_10 addq.l #2,a5 move.l #80000,d0 bsr.s fread tst.l d0 bmi fehler subq.l #4,a5 move.w d6,-(sp) move.w #62,-(sp) trap #1 addq.l #4,sp move.l a5,4(a5) move.l a5,a0 clr.w d0 move.w #$ff,d1 itpol: add.w (a0)+,d0 dbra d1,itpol move.w #$5678,d1 sub.w d0,d1 move.w d1,10(a5) jsr 16(a5) move.l 4(sp),a1 sub.l a1,a0 clr.w -(sp) move.l a0,-(sp) move.w #$31,-(sp) trap #1 fread: move.l a5,-(sp) move.l d0,-(sp) move.w d6,-(sp) move.w #63,-(sp) trap #1 lea 12(sp),sp rts fehler: lea t_nles(pc),a0 bsr.s pr_strg move.w #7,-(sp) trap #1 addq.l #2,sp bra termy pr_strg: move.l a0,-(sp) move.w #9,-(sp) trap #1 addq.l #6,sp rts section data t_datna: dc.b 'st_speed.bin',0 t_nles: dc.b 27,'E',13,10,' Diskerror ! *** Not installed *** ',0 t_inf: dc.b 27,'E',13,10 dc.b ' ST-SPEED Version 1.x installed.',13,10 dc.b 13,10 dc.b ' (c) MAXON Computer GmbH 1990',13,10 dc.b 0 even tot_end: end * * "ST-SPEED" - (c) MAXON Computer GmbH 1990 * * Programmcode muß verschiebbar sein! * (deshalb LEA xxx(pc),Ax TST (Ax) !) * * Programm unterstützt XBRA-Methode * Kennung: "SPxx". xx gibt Versionsnummer an. * * Geschrieben mit Devpac-ST V2.0 von HiSoft. * opt o+,p+ * Optimier, Abs.Code zeilen: equ 12*16*80-1 etv_critic: equ $404 * Critical-Error-Hdlr hdv_bpb: equ $472 * GETBPB-Vektor hdv_rw: equ $476 * RWABS-Vektor hdv_mediach: equ $47e * Mediach-Vektor drvbits: equ $4c2 * Drvbits-Sysvar _vblqueue: equ $456 * VBL-Liste _dumpflg: equ $4ee * Hardcopy-Flag _sysbase: equ $4f2 _bootdev.hi: equ $446 _bootdev.lo: equ $447 vbl_slot: equ 28 * VBL-Slot #7 kennung: equ 'SP10' version: equ '1' revision: equ '0' output \st_speed.bin PRINT: MACRO pea \1 move.w #9,-(sp) * PRINT trap #1 addq.l #6,sp ENDM SUP_EXEC: MACRO pea \1 move.w #$26,-(sp) * SUP_EXEC trap #14 addq.l #6,sp ENDM MALLOC: MACRO move.l \1,-(sp) move.w #$48,-(sp) * MALLOC trap #1 addq.l #6,sp ENDM SETBLOCK: MACRO move.l \1,-(sp) move.l \2,-(sp) clr.w -(sp) move.w #$4a,-(sp) * SETBLOCK trap #1 lea 12(sp),sp ENDM FCREATE: MACRO clr.w -(sp) * Normale Datei pea \1 * Dateiname move.w #$3c,-(sp) * FCREATE trap #1 addq.l #8,sp ENDM FWRITE: MACRO pea \1 * Adresse move.l \2,-(sp) * Bytes move.w \3,-(sp) move.w #$40,-(sp) * FWRITE trap #1 lea $c(sp),sp ENDM FCLOSE: MACRO move.w \1,-(sp) move.w #$3e,-(sp) * FCLOSE trap #1 addq.l #4,sp ENDM FOPEN: MACRO clr.w -(sp) * Lesen pea \1 * Dateiname move.w #$3d,-(sp) * FOPEN trap #1 addq.l #8,sp ENDM FREAD: MACRO pea \1 * Save-Area move.l \2,-(sp) * Bytes move.w \3,-(sp) move.w #$3f,-(sp) * FREAD trap #1 lea $c(sp),sp ENDM REINS_VEC:MACRO lea \1,a0 * Vector-Adr. move.l \2,d0 * Alter Inhalt bsr vector_reinstall ENDM progstart:dc.l $12123456 * TOS-MAGIC 1 dc.l 0 * TOS-ADRESS bra.s res_mem * TOS-START dc.w 0,$1029,$3847 * ALIGN + MY-MAGIC ********* Einsprung vom Lader aus movem.l d0-d7/a0-a6,-(sp) bsr m_load2 * Parms laden SUP_EXEC installvec(pc) * Prg in VBL SUP_EXEC initoldvec1(pc) * RAMDISK SUP_EXEC initoldvec2(pc) * FILE-Prot PRINT install(pc) moveq.l #-1,d0 moveq.l #1,d1 njump: mulu #9999,d1 mulu #9999,d1 dbra d0,njump * Zeitverzög. movem.l (sp)+,d0-d7/a0-a6 lea res_end(pc),a0 add.l #zeilen+l,a0 * Ende melden rts ********* Programm in die VBL-QUEUE einbinden * Einsprung vom TOS nach einem RESET res_mem: movem.l d0-d7/a0-a6,-(sp) MALLOC #80000 * Speicher res. lea res_end(pc),a1 add.l #zeilen+1,a1 * berechnen und move.l a1,d1 * verkleinern sub.l d0,d1 SETBLOCK d1,d0 * schützen bsr file_reinstall * alter Vektor! lea fileflag(pc),a0 * Protect? tst.w (a0) beq.s res_mem1 * Nein... bsr file_install * Vektoren res_mem1: bsr ramdisk_vec_reinstall * RAMDISK-Vektoren reinstallieren! bsr initoldvec1 * alte Vektoren lea installflag(pc),a0 tst.w (a0) beq no_ramdisk * keine da lea resident(pc),a0 tst.w (a0) bne.s resdisk * reset-resident! lea installflag(pc),a0 * wenn nicht resident, dann clr.w (a0) * Disk abmelden move.l drvbits,d0 * Bit in Sysvar clr.l d1 * löschen move.w driveno(pc),d1 tst.w d1 beq.s no_ramdisk bclr d1,d0 move.l d0,drvbits bra.s no_ramdisk resdiik: MALLOC #-1 * Ber. schützen sub.l #30000,d0 * 30 kB MALLOC d0 lea mfree(pc),a0 clr.l (a0) * Je. Reinst. move.l puffer(pc),d1 * Adr. RAMDISK add.l groesse(pc),d1 * +Größe sub.l d0,d1 * - Blockanfang SETBLOCK d1,d0 move.l drvbits,d0 * anmelden clr.l d1 move.w driveno(pc),d1 bset d1,d0 move.l d0,drvbits no_ramdisk: movem.l (sp)+,d0-d7/a0-a6 installvec: movem.l d0/a0/a2,-(sp) lea start(pc),a2 * Start move.l _vblqueue,a0 * Start VBLANK move.l a2,vbl_slot(a0) * in VBL move sr,-(sp) * Floppy aus or.w #$700,sr move.b #14,$ffff8800.w * Port A move.b $ffff8800.w,d0 * aktuellen Wert holen and.b #$f8,d0 or.b #5,d0 * LW A, Seite 0 move.b d0,$ffff8802.w * in Port A move (sp)+,sr movem.l (sp)+,d0/a0/a2 rts initoldvec1: lea o_bpb(pc),a0 * alter BPB move.l hdv_bpb,(a0) lea o_rw (pc),a0 * alter RW move.l hdv_rw,(a0) lea o_media(pc),a0 * alter MEDIA move.l hdv_mediach,(a0) lea mybpb(pc),a0 * Vektoren move.l a0,hdv_bpb lea myrwabs(pc),a0 move.l a0,hdv_rw lea mymedia(pc),a0 move.l a0,hdv_mediach rts initoldvec2: lea trap1_old(pc),a0 * alter TRAP-1-Vektor move.l $84.w,(a0) lea fileflag(pc),a0 tst.w (a0) beq.s kein_fileprotect1 * kein Fileprotect bsr file_install * Vektoren bra.s initoldvecend kein_fileprotect1: bsr file_reinstall * Vektoren initoldvecend: rts ********* Anfang Hauptroutine dc.b 'XBRA' dc.l kennung dc.l 0 start: move.l a0,-(sp) lea speedflag(pc),a0 tst.w (a0) * verlangsamen? bne.s speedwait * Ja... timeout: move.l (sp)+,a0 tst.w $4ee.w * ALT+HELP? beq.s haupt * Ja ! rts speedwait:move.l d0,-(sp) move.l speedtime(pc),d0 time1: nop dbra d0,time1 move.l (sp)+,d0 bra.s timeout ********* ALT+HELP wurde gedrückt haupt: lea menueflag(pc),a0 tst.w (a0) * Menü anzeigen bne.s schleife * Nein bsr maus_aus * Maus aus bsr sichere_screen * Screen si. menue: bsr loesche_screen * Screen lö. PRINT text(pc) * Text ausgeben schleife: bsr inkey * Tast.-Abfrage bset #5,d0 * Nur Kleinb. cmpi.b #'h',d0 * Hardcopy beq m_hardcopy * drucken! cmpi.b #'q',d0 * Zurück zum beq.s m_quit * Programm cmpi.b #' ',d0 * wie Q beq.s m_quit cmpi.b #'c',d0 * Synchronisatonl beq m_sync * 50 <-> 60 Hz cmpi.b #'a',d0 * Menümldg I/O beq m_menueaa cmpi.b #'p',d0 * RESET kalt beq.s m_reset cmpi.b #'r',d0 * RESET warm beq m_reset1 cmpi.b #'d',d0 * RAMDISK beq m_startram cmpi.b #'b',d0 * BOOT-Device beq m_bootdevice cmpi.b #'w',d0 * WRITE-Prot beq m_write cmpi.b #'s',d0 * SAVE-Default beq m_save cmpi.b #'l',d0 * LOAD-Default beq m_load cmpi.b #'x',d0 * XBRA-List beq m_xbra cmpi.b #'i',d0 * Systeminfo beq m_stspeed cmpi.b #'f',d0 * File-Protect beq m_file cmpi.b #'0’,d0 * Tasten-Code>=0 bge.s speed * Ja ! notspeed: bra schleife speed: cmpi.b #'9',d0 * Tasten-Code<=9 ble speed1 * Ja ! bra.s notspeed ********* Zurück zun Programm oder GEM—DESKTOP m_quit: lea menueflag(pc),a0 tst.w (a0) bne.s ende bsr hole_screen * Screen zurück ende: move.w #-1,_dumpflg * Hardcopy-Flag lea menueflag(pc),a0 tst.w (a0) bne.s ende1 bsr maus_an * Maus an ende1: rts * Zurück ********* reset m_reset: lea progstart(pc),a0 *Kill Magic clr.l (a0) REINS_VEC $84,trap1_old(pc) * TRAP-1 lea installflag(pc),a0 * RAMDISK tst.w (a0) beq.s m_reset1 * Nein... bsr ramdisk_vec_reinstall move.l drvbits,d0 clr.l d1 move.w driveno(pc),d1 tst.w d1 beq.s m_reset1 bclr d1,d0 move.l d0,drvbits m_reset1: move.l _sysbase,a0 * in RESET-Vek. jmp (a0) ********* Ausgabe einer Hardcopy m_hardcopy: lea menueflag(pc),a0 tst.w (a0) bne.s hard1 bsr hole_screen hard1: move.w #20,-(sp) * XBIOS 20 trap #14 addq.l #2,sp bra.s ende ********* Synchronisation 50 <—> 60 Hz m_sync: bchg.b #1,$ffff820a.w bra menue ********* Verändern der Geschwindigkeit speed1: cmpi.b #'0',d0 beq.s speednormal clr.l d1 move.b d0,d1 sub.b #48,d1 * Taste 1 bis 9 mulu #1070,d1 lea speedtime(pc),a0 move.l d1,(a0) lea speedflag(pc),a0 move.w #-1,(a0) bra m_quit speednormal: lea speedflag(pc),a0 clr.w (a0) lea speedtime(pc),a0 clr.l (a0) bra m_quit ********* Menüflag invertieren m_menueaa:lea menueflag(pc),a0 not.w (a0) move.w #-1,_dumpflg tst.w (a0) beq ende1 bsr hole_screen bsr maus_an bra ende1 ********* BOOT-Device m_bootdevice: lea menueflag(pc),a0 tst.w (a0) bne m_quit bsr loesche_screen PRINT boottext(pc) move.l drvbits,d0 * Drvbits holen move.w #-1,d1 * Startwert, LW ffdlp: addq.w #1,d1 * nächstes LW cmp.w #16,d1 * schon 16? beq.s fende * ja, Fehler btst d1,d0 * LW inst.? beq.s ffdlp movem.l d0/d1,-(sp) add.w #65,d1 * ASCII move.w d1,-(sp) * Laufwerk move.w #2,-(sp) trap #1 addq.l #4,sp PRINT spaces(pc) movem.l (sp)+,d0/d1 bra.s ffdlp fende: bsr inkey bclr #5,d0 cmp.b #'Q',d0 beq menue ext.w d0 sub.w #65,d0 move.l drvbits,d1 btst d0,d1 bne.s fok bra.s fende fok: move.b d0,_bootdev.hi * Laufwerk in LOW- und HIGH-Byte move.b d0,_bootdev.lo * eintragen. Falls ein gepatchtes TOS bra menue * verwendet wird, durch * MOVE.W D0,_BOOTDEV.HI ersetzen ********* Systeminfo m_stspeed:lea menueflag(pc),a0 tst.w (a0) bne m_quit bsr loesche_screen PRINT st_speedl(pc) * Freier Spei. MALLOC #-1 move.l d0, d1 lea freezahl(pc),a2 bsr binasc PRINT freezahl(pc) * Memory PRINT st_speed2(pc) * Drives bsr show_protected PRINT st_speed3(pc) * Massage lea installflag(pc),a0 * Ramdisk vorhanden? tst.w (a0) bne memdisk * Ja... PRINT line(pc) bra.s st_jump memdisk: move.l groesse(pc),d1 lea freezahl(pc),a2 bsr binasc PRINT freezahl(pc) st_jump: lea filepmode(pc),a0 * File-Prot. move.b #'O',(a0)+ * = An move.b #'N',(a0)+ move.b #' ',(a0)+ lea fileflag(pc),a1 tst.w (a1) bna.s st_jump1 move.b #'F',-(a0) * Prot, aus move.b #'F',-(a0) st_jump1: PRINT fileptext(pc) PRINT filetext1(pc) PRINT fileptext1(pc) bsr wait bra menue sens
Stephan Slabihoud