@C9coding hints and cheats

@C6
Kleiner Tip zum SWI "Wimp_PollIdle"
@C7
Viele Wimpprogramme haben die dumme Angewohnheit, den Wimp_Poll mit dem Reason-
code 0 aufzurufen, um die Kontrolle schnellstmglich wiederzuerlangen. Dabei
brauchen sie diese meist nicht, rufen hchstens einen SWI auf um zu schauen, was
los ist und geben dann wieder zurck. Das kostet aber extrem viel Poll-Zeit, die
andere Wimpprogramme viel dringender brauchen. Da nur die wenigsten Programme
wirklich zu jedem Wimppoll aufgerufen werden mssen sondern einmal pro Sekunde
mehr als genug sein drfte, sollte man den SWI "Wimp_PollIdle" benutzen, dieser
nimmt die selben Eingabekonditionen wie der SWI "Wimp_Poll", jedoch mu in R2
die frheste Rckrufzeit stehen. Diese richtet sich nach der Monotonic Time,
d.h. wenn der Wimp_PollIdle die Routine in einer Sekunde das nchste mal auf-
rufen soll mu der Code so aussehen
@C3
  SYS "OS_ReadMonotonicTime"TOA%
  SYS "Wimp_PollIdle",0,Block%,A%+100
@C7
dabei ist darauf zu achten, da der Nullevent nicht ausgeblendet wird, da ja der
PollIdle versucht, die Routine mit dem Nullevent aufzurufen.

@C1
@C6
BASIC Funktionen im BASIC Inline Assembler
@C7
Im BASIC Inline Assembler ist es mglich, anwenderdefinierte Funktionen (FN`s)
aufzurufen, ohne mit [ den Assembler kurzzeitig zu verlassen. Man mu nicht ein-
mal eine Zielvariable angeben.
@C3
  MOV R0,#123                   ; unwichtiges asm zeuch
  EOR R0,R0,R0
  @CBFNmyfunction@C3                  ; Aufruf der Funktion
  MOV PC,R14
@C7
Damit ist es mglich, eigene Erweiterungen der Befehle des Inlineassemblers
vorzunehmen, was das Programmieren extrem erleichtert. Einige Beispiele seien
hier gebracht:

- Workspace reservieren
  Diese Funktion reserviert einen Block in der angegebenen Gre. Dazu erhht
  man die Assemblerzieladressen P% und O% um die angegebene Zahl.
  bytes.
@C3
  DEF FNworkspace(Groesse%)
    P%+=Groesse%
    O%+=Groesse%
  =0
@C7
  Anwendungsbeispiel:
@C3
  .tempblock FNworkspace(512)   ; reserviere 512 Bytes fr temp daten
@c7

- Einen Block mit Bytes fllen
  Diese Funktion fllt einen Speicherblock gegebener Gre mit einem ebenfalls
  angegebenem Wert.
@C3
  DEF FNfillb(length%,value%) LOCAL I%
    FOR I%=P% TO P%+length%
    ?I%=value%
    NEXT I%
    P%+=length%
  =0
@c7
  Wenn man Offset Assemblierung benutzt (Bit 2 der OPT-Variable ist gesetzt),
  mu O% als Zieladresse benutzt werden und O% und P% erhht werden. Die folgen-
  de Routine liefert das geforderte:
@C3
  DEF FNfillb(length%,value%) LOCAL I%
    FOR I%=O% TO O%+length%
    ?I%=value%
    NEXT I%
    P%+=length%
    O%+=length%
  =0
@C7
  Anwendungsbeispiel:
@C3
  .datalabel FNfillb(1024,0)    ; flle einen Block von 1024 Bytes mit 0
@C7

- externe Files in das Programm einfgen:
@C3
  DEF FNfile(name$) LOCAL I%
    SYS "OS_File",16,name$,P% TO ,,,,I%
    P%+=I%
  =0
@C7
  Wie schon erwhnt braucht man auch hier noch die Routine fr Offset assemb-
  lierung:
@C3
  DEF FNfile(name$) LOCAL I%
    SYS "OS_File",16,name$,O% TO ,,,,I%
    P%+=I%:O%+=I%
  =0
@C7
  Anwendungsbeispiel:
@C3
  .picture FNfile("hotgirl")    ; Raw Grafik Daten...
@C7

- Eine Reihe von Instruktionen vom Assemblieren ausschlieen
  Die nchsten beiden Routinen sind dazu da, alle von ihnen eingeschlossenen
  Instructionen werden nicht mitassembliert. Dies ist fr das Debuggen von Pro-
  grammen sehr ntzlich: Um eine bestimmtes Stck Quellcode vom Assemblieren
  auszuschlieen, mu man nicht vor jede Instruktion ein ';' schreiben,
  'FNremon' vor und 'FNremoff' nach dem Block reichen aus:
@C3
  DEF FNremon
    remptr%=P%
  =0

  DEF FNremoff
    O%-=P%-remptr%
    P%-=P%-remptr%
  =0
@C7
  Anwendungsbeispiel:
@C3
  MOV R0,#&2000000
  FNremon
  STMDB R0!,{R1-R8}             ; Dies nicht mitassemblieren
  FNremoff
  CMP R0,R9
  BNE blabla

@C1
@C6
Filenames abtrennen
@C7
Oft hat ein Wimpprogramm, das mit Files hantiert das Problem, Filenames von den
Pathnames abzutrennen, das heit, da das Programm nur die wirklichen (meist) 10
Buchstaben des Files braucht. Die einfachste Routine dies zu tun sieht so aus:

@C3WHILE INSTR$(File$,".")>0
 File$=MID$(File$,INSTR$(File$,".")+1)
ENDWHILE@C7

@C1
@C6
Nervende Festplatten
@C7
Festplatten sind etwas tolles... jedoch gehen einige Exemplare nach einiger Zeit
durch ihre Lautstrke ziemlich auf die Nerven. Dabei bieten ADFS Festplatten
(zumindest die meisten) einen SpinDown-SWI. Also braucht man keine Kilobytes-
schluckende Applikationen, die sowas vielleicht anbieten, das folgende File
einfach auf die Pinnwand pinnen und im 'Notfall' starten. An Stelle von xx trgt
man die entsprechende Drivenummer der Festplatte ein.

@C3SYS "ADFS_PowerControl",2,xx,0@C7

bzw. die Assemblerversion:

@C3MOV  R0,#2
MOV  R1,#xx
MOV  R2,#0
SWI  "ADFS_PowerControl"
MOV  PC,R14@C7

@C1
@C6
Unser Soundsystem
@C7
Nun sage noch einer, das Soundsystem des Archimedes liee sich nicht einfach
steuern, mit einer einfachen Routine lassen sich Zufallsmusiken erzeugen, die
erste produziert Schlagzeugklnge, die zweite unterlegt diese mit Melodieinstru-
menten.

@C3SYS "Sound_Enable",2
SYS "Sound_AttachVoice",1,6
REPEAT
SYS "Sound_Configure",0,0,RND(55)
SYS &100 + 7
FOR I% = 1 TO 8 : SYS "OS_Byte",19 : NEXT
UNTIL 0

SYS "Sound_Enable",2
REPEAT
IF RND(2) =1 THEN SYS "Sound_AttachVoice",1,4 ELSE SYS "Sound_AttachVoice",1,7
SYS "Sound_Configure",0,0,RND(55)
SYS &100 + 7
FOR I% = 1 TO 8 : SYS "OS_Byte",19 : NEXT
UNTIL 0@C7

@C1
@C6
Zum Tastaturauslesen
@C7
Viele kennen und benutzen den BASIC Befehl INKEY(x). Dabei wissen die meisten
gar nicht, da man damit auch einzelne Tasten auslesen kann, und wenn, dann
wissen sie nicht, wie. Ist das x negativ, wird wie gesagt die Taste gecheckt,
jedoch nicht, wie man vielleicht vermutet, die Taste, deren ASCII code -x ist,
sondern es wird das selbe Tastaturformat verwandt, wie im OS_Byte 121. Dies ist
nmlich die interne Keynummer. Das x ist dann die bitinvertierte (NOT) Keynum-
mer. Eine Liste der Keynummern gibt es im erweiterten StrongHelp, es liegt aber
auch eine Liste im Bits Verzeichnis.

@C1
@C6
Vorsicht mit LZW
@C7
Das Module LZW benutzt bei seinen Compress bzw. Decompress- SWI`s den Bild-
schirmspeicher als Buffer. Dessen Anfangsadresse liest er aber nur beim ersten
Start aus. Sollte sich nun durch einen Moduswechsel diese Adresse nach oben
verschieben, liegt die als erstes ausgelesene Startadresse auerhalb des be-
schreibbaren Speicherbereichs. Das fhrt dann unweigerlich zu Fehlern. Abhilfe
schafft das reinitialisieren des Modules nach einem Modechange.

@C1
@C6
FOR NEXT Schleifen elegant beenden
@C7
Um zwei verschachtelte FOR - NEXT Schleifen zu beenden, mu man die beiden Lauf-
variablen nicht extra spezifizieren. Bei EINER einfachen Schleife reicht, wie
bekannt ein '@C3NEXT@C7', bei ZWEI Schleifen ein '@C3NEXT,@C7'. Zu Veranschaulichung:

@C3FOR I% = 0 TO 20
FOR J% = 0 TO 15
PRINT TAB(I%,J%)"O";
NEXT,@C7


