From 2502c040a03d26016b1883a7e61f4d29be2203fb Mon Sep 17 00:00:00 2001 From: Sandy Pleyte Date: Tue, 7 Nov 2017 19:20:39 +0100 Subject: [PATCH] Updated docs --- Future Disk/02/Cirkels in ML.md | 173 --- Future Disk/02/Machinetaal 3.md | 227 ---- Future Disk/03/Machinetaal 4.md | 221 ---- Future Disk/04/Machinetaal 5.md | 287 ----- Future Disk/05/Machinetaal 6.md | 168 --- Future Disk/05/Special Effects BASIC.md | 216 ---- Future Disk/06/Machinetaal 7.md | 203 ---- Future Disk/06/Special Effects BASIC 2.md | 221 ---- Future Disk/07/Machinetaal 8.md | 229 ---- Future Disk/07/Special Effects BASIC 3.md | 218 ---- Future Disk/075/Machinetaal Cursus 9.md | 204 ---- Future Disk/075/Special Effects BASIC 4.md | 593 --------- Future Disk/075/Turbo-R Basic.md | 184 --- Future Disk/10/Machinetaal 10.md | 273 ----- Future Disk/10/Special Effects BASIC 5.md | 174 --- Future Disk/11/Machinetaal 11.md | 128 -- Future Disk/11/Pascal 1.md | 51 - Future Disk/12/Pascal 2.md | 158 --- Future Disk/12/Special Effects BASIC 5.md | 205 ---- Future Disk/13/Machinetaal 12.md | 145 --- Future Disk/13/Pascal 3.md | 153 --- Future Disk/14/Pascal 4.md | 150 --- Future Disk/15/Data compressie.md | 103 -- Future Disk/15/Pascal 5.md | 85 -- Future Disk/15/The 2+ Corner.md | 118 -- Future Disk/17/Basic Cursus 6.md | 117 -- Future Disk/17/Data compressie 2.md | 141 --- Future Disk/17/Pascal 6.md | 245 ---- Future Disk/18/Data compressie 3.md | 316 ----- Future Disk/18/Mooblaster Music Cursus.md | 204 ---- Future Disk/18/Pascal 7.md | 148 --- Future Disk/18/Undocumented Z80 code.md | 57 - Future Disk/19/Basic Cursus 8.md | 77 -- Future Disk/19/Basic voor beginners.md | 89 -- Future Disk/19/Looplichtjes 2.md | 39 - Future Disk/19/MSX2+ Schermen in BASIC.md | 169 --- Future Disk/19/Mcode Special 1.md | 181 --- Future Disk/19/Moonblaster Music Cursus 2.md | 90 -- Future Disk/19/Pascal 8.md | 382 ------ Future Disk/20/Data compressie 4.md | 29 - Future Disk/20/Moonblaster Music Cursus 3.md | 158 --- Future Disk/20/Muizen in BASIC.md | 101 -- Future Disk/20/Turbo-R BASIC.md | 177 --- Future Disk/21/Call Kanji.md | 178 --- Future Disk/21/MCode Special 2.md | 202 ---- Future Disk/21/Moonblaster Music Cursus 4.md | 101 -- Future Disk/21/Screen 12.md | 75 -- Future Disk/22/Data compressie 5.md | 1055 ----------------- Future Disk/22/Moonblaster Music Cursus 5.md | 324 ----- Future Disk/23/MCode Special 3.md | 256 ---- Future Disk/24/2+ Schermen.md | 149 --- Future Disk/24/V9958 in ML.md | 79 -- Future Disk/25/Clock chip.md | 154 --- Future Disk/25/MCode Special 4.md | 282 ----- Future Disk/25/MSX-DOS2 deel 1.md | 193 --- Future Disk/27/Mcode Special 5.md | 119 -- Future Disk/28/MSX-DOS2 deel 2.md | 94 -- Future Disk/28/MSX-DOS2 deel 3.md | 96 -- Future Disk/28/The PCM sample processor.md | 102 -- Future Disk/30/Advanced Basic.md | 90 -- Future Disk/30/Assembly voor beginners.md | 106 -- Future Disk/30/Paint in ML.md | 78 -- Future Disk/31/Advanced Basic 2.md | 221 ---- Future Disk/31/Disk IO in BASIC.md | 236 ---- Future Disk/32/Pascal cursus 1 EN.md | 103 -- Future Disk/32/Pascal cursus 1 NL.md | 156 --- Future Disk/32/Pascal cursus 2 EN.md | 83 -- Future Disk/32/Pascal cursus 2 NL.md | 159 --- Future Disk/32/Screen 4.md | 194 --- Future Disk/33/Advanced Basic 3.md | 92 -- Future Disk/33/Assembly Cursus 2.md | 109 -- Future Disk/33/Bits en bull.md | 259 ---- Future Disk/33/Pascal 3.md | 150 --- Future Disk/33/Pascal 4.md | 148 --- Future Disk/34/Advanced Basic 4.md | 150 --- Future Disk/34/Assembly cursus 3.md | 186 --- Future Disk/34/Pascal 5.md | 333 ------ Future Disk/35/Assembly cursus 4.md | 165 --- Future Disk/35/Copy in BASIC.md | 82 -- Future Disk/35/Pascal 7.md | 146 --- Future Disk/35/Pascal 8.md | 381 ------ Future Disk/36/Advanced Basic 5.md | 108 -- Future Disk/36/Assembly cursus 5.md | 110 -- Future Disk/36/Datacompressie 2.md | 145 --- Future Disk/36/Mathpack 2.md | 109 -- Future Disk/36/ROM images laden.md | 112 -- Future Disk/36/Recursie 2.md | 121 -- Future Disk/37/Advanced Basic 6.md | 102 -- Future Disk/37/Assembly cursus 6.md | 830 ------------- Future Disk/37/Mathpack 3.md | 91 -- Future Disk/38/Assembly cursus 7.md | 138 --- Future Disk/40/Assembly cursus 8.md | 63 - Future Disk/40/Schuiven en roteren.md | 131 -- Future Disk/42/Assembly cursus 9.md | 453 ------- Sunrise Special/1/Disk cursus special 1.md | 647 ---------- Sunrise Special/1/Geheugen tellen.md | 312 ----- Sunrise Special/1/Het rel file formaat.md | 60 - Sunrise Special/1/Hybride programmeren.md | 647 ---------- Sunrise Special/1/MSX Assemblers.md | 274 ----- Sunrise Special/1/Memman 2.3 intro.md | 391 ------ Sunrise Special/1/Memman 2.3 specificaties.md | 641 ---------- Sunrise Special/1/Muis uitlezen.md | 216 ---- Sunrise Special/1/Pointers in Pascal.md | 178 --- Sunrise Special/1/Recursief programmeren.md | 150 --- Sunrise Special/1/Rel assembleren.md | 173 --- Sunrise Special/1/Set scroll in basic.md | 108 -- .../1/Te zachte PSG bij de NMS 8250 55 80.md | 36 - Sunrise Special/1/Track 0 op de turbo-r.md | 78 -- Sunrise Special/2/Cursus dd-graph.md | 448 ------- Sunrise Special/2/Geheugen schakelen.md | 480 -------- .../2/Interrupt service routines.md | 801 ------------- .../MSX-DOS 2 voor machinetaalprogrammeurs.md | 428 ------- Sunrise Special/2/MSX-DOS 2.31.md | 186 --- .../2/Macro commandos met gen80.md | 258 ---- Sunrise Special/2/Memman 2.42.md | 76 -- Sunrise Special/2/PCM Sampler.md | 760 ------------ Sunrise Special/2/PCM routines van de bios.md | 84 -- Sunrise Special/2/Pauze toets.md | 258 ---- Sunrise Special/2/Programmeer taal c 2.md | 272 ----- Sunrise Special/2/Programmeer taal c.md | 587 --------- .../2/Rechtstreeks via PCM afspelen.md | 123 -- Sunrise Special/2/Stereo SCC.md | 20 - Sunrise Special/2/VDP Cursus 1.md | 418 ------- Sunrise Special/2/VDP Cursus 2.md | 455 ------- .../3/De archeologie van de MSX.md | 222 ---- .../3/De programmeertaal C deel 3.md | 616 ---------- .../3/De programmeertaal C deel 4.md | 464 -------- Sunrise Special/3/File handles.md | 185 --- Sunrise Special/3/Getallen printen.md | 213 ---- Sunrise Special/3/Hybride Call Commando's.md | 567 --------- Sunrise Special/3/Memman problemen.md | 242 ---- Sunrise Special/3/Programmeren sample chip.md | 176 --- Sunrise Special/3/Scrollen in kun basic.md | 72 -- Sunrise Special/3/TSR Change CPU.md | 236 ---- Sunrise Special/3/TSR Development kit.md | 91 -- Sunrise Special/3/TSR Volume Input Meter.md | 316 ----- Sunrise Special/3/Turbo Pascal Patch.md | 76 -- Sunrise Special/3/Turbo-R systeemcounter.md | 153 --- Sunrise Special/3/VDP Commando Registers.md | 326 ----- Sunrise Special/3/VDP Cursus 3.md | 274 ----- Sunrise Special/3/VDP Cursus 4.md | 384 ------ Sunrise Special/3/Werken met ASCII C.md | 167 --- future_disk/15/Looplichtje.md | 50 + future_disk/21/Ledjes.md | 69 ++ future_disk/21/Recursie.md | 128 ++ future_disk/27/Rotatie.md | 329 +++++ future_disk/34/mathpack.md | 195 +++ future_disk/35/Datacompressie.md | 72 ++ future_disk/42/lijntjes.md | 106 ++ sunrise_special/1/r800.md | 857 +++++++++++++ sunrise_special/2/Blinkmode.md | 797 +++++++++++++ sunrise_special/2/Ledjes.md | 324 +++++ sunrise_special/2/Resource.md | 248 ++++ sunrise_special/2/cdd.md | 244 ++++ sunrise_special/2/redirection.md | 147 +++ sunrise_special/3/Getdisk.md | 68 ++ 156 files changed, 3634 insertions(+), 31551 deletions(-) delete mode 100644 Future Disk/02/Cirkels in ML.md delete mode 100644 Future Disk/02/Machinetaal 3.md delete mode 100644 Future Disk/03/Machinetaal 4.md delete mode 100644 Future Disk/04/Machinetaal 5.md delete mode 100644 Future Disk/05/Machinetaal 6.md delete mode 100644 Future Disk/05/Special Effects BASIC.md delete mode 100644 Future Disk/06/Machinetaal 7.md delete mode 100644 Future Disk/06/Special Effects BASIC 2.md delete mode 100644 Future Disk/07/Machinetaal 8.md delete mode 100644 Future Disk/07/Special Effects BASIC 3.md delete mode 100644 Future Disk/075/Machinetaal Cursus 9.md delete mode 100644 Future Disk/075/Special Effects BASIC 4.md delete mode 100644 Future Disk/075/Turbo-R Basic.md delete mode 100644 Future Disk/10/Machinetaal 10.md delete mode 100644 Future Disk/10/Special Effects BASIC 5.md delete mode 100644 Future Disk/11/Machinetaal 11.md delete mode 100644 Future Disk/11/Pascal 1.md delete mode 100644 Future Disk/12/Pascal 2.md delete mode 100644 Future Disk/12/Special Effects BASIC 5.md delete mode 100644 Future Disk/13/Machinetaal 12.md delete mode 100644 Future Disk/13/Pascal 3.md delete mode 100644 Future Disk/14/Pascal 4.md delete mode 100644 Future Disk/15/Data compressie.md delete mode 100644 Future Disk/15/Pascal 5.md delete mode 100644 Future Disk/15/The 2+ Corner.md delete mode 100644 Future Disk/17/Basic Cursus 6.md delete mode 100644 Future Disk/17/Data compressie 2.md delete mode 100644 Future Disk/17/Pascal 6.md delete mode 100644 Future Disk/18/Data compressie 3.md delete mode 100644 Future Disk/18/Mooblaster Music Cursus.md delete mode 100644 Future Disk/18/Pascal 7.md delete mode 100644 Future Disk/18/Undocumented Z80 code.md delete mode 100644 Future Disk/19/Basic Cursus 8.md delete mode 100644 Future Disk/19/Basic voor beginners.md delete mode 100644 Future Disk/19/Looplichtjes 2.md delete mode 100644 Future Disk/19/MSX2+ Schermen in BASIC.md delete mode 100644 Future Disk/19/Mcode Special 1.md delete mode 100644 Future Disk/19/Moonblaster Music Cursus 2.md delete mode 100644 Future Disk/19/Pascal 8.md delete mode 100644 Future Disk/20/Data compressie 4.md delete mode 100644 Future Disk/20/Moonblaster Music Cursus 3.md delete mode 100644 Future Disk/20/Muizen in BASIC.md delete mode 100644 Future Disk/20/Turbo-R BASIC.md delete mode 100644 Future Disk/21/Call Kanji.md delete mode 100644 Future Disk/21/MCode Special 2.md delete mode 100644 Future Disk/21/Moonblaster Music Cursus 4.md delete mode 100644 Future Disk/21/Screen 12.md delete mode 100644 Future Disk/22/Data compressie 5.md delete mode 100644 Future Disk/22/Moonblaster Music Cursus 5.md delete mode 100644 Future Disk/23/MCode Special 3.md delete mode 100644 Future Disk/24/2+ Schermen.md delete mode 100644 Future Disk/24/V9958 in ML.md delete mode 100644 Future Disk/25/Clock chip.md delete mode 100644 Future Disk/25/MCode Special 4.md delete mode 100644 Future Disk/25/MSX-DOS2 deel 1.md delete mode 100644 Future Disk/27/Mcode Special 5.md delete mode 100644 Future Disk/28/MSX-DOS2 deel 2.md delete mode 100644 Future Disk/28/MSX-DOS2 deel 3.md delete mode 100644 Future Disk/28/The PCM sample processor.md delete mode 100644 Future Disk/30/Advanced Basic.md delete mode 100644 Future Disk/30/Assembly voor beginners.md delete mode 100644 Future Disk/30/Paint in ML.md delete mode 100644 Future Disk/31/Advanced Basic 2.md delete mode 100644 Future Disk/31/Disk IO in BASIC.md delete mode 100644 Future Disk/32/Pascal cursus 1 EN.md delete mode 100644 Future Disk/32/Pascal cursus 1 NL.md delete mode 100644 Future Disk/32/Pascal cursus 2 EN.md delete mode 100644 Future Disk/32/Pascal cursus 2 NL.md delete mode 100644 Future Disk/32/Screen 4.md delete mode 100644 Future Disk/33/Advanced Basic 3.md delete mode 100644 Future Disk/33/Assembly Cursus 2.md delete mode 100644 Future Disk/33/Bits en bull.md delete mode 100644 Future Disk/33/Pascal 3.md delete mode 100644 Future Disk/33/Pascal 4.md delete mode 100644 Future Disk/34/Advanced Basic 4.md delete mode 100644 Future Disk/34/Assembly cursus 3.md delete mode 100644 Future Disk/34/Pascal 5.md delete mode 100644 Future Disk/35/Assembly cursus 4.md delete mode 100644 Future Disk/35/Copy in BASIC.md delete mode 100644 Future Disk/35/Pascal 7.md delete mode 100644 Future Disk/35/Pascal 8.md delete mode 100644 Future Disk/36/Advanced Basic 5.md delete mode 100644 Future Disk/36/Assembly cursus 5.md delete mode 100644 Future Disk/36/Datacompressie 2.md delete mode 100644 Future Disk/36/Mathpack 2.md delete mode 100644 Future Disk/36/ROM images laden.md delete mode 100644 Future Disk/36/Recursie 2.md delete mode 100644 Future Disk/37/Advanced Basic 6.md delete mode 100644 Future Disk/37/Assembly cursus 6.md delete mode 100644 Future Disk/37/Mathpack 3.md delete mode 100644 Future Disk/38/Assembly cursus 7.md delete mode 100644 Future Disk/40/Assembly cursus 8.md delete mode 100644 Future Disk/40/Schuiven en roteren.md delete mode 100644 Future Disk/42/Assembly cursus 9.md delete mode 100644 Sunrise Special/1/Disk cursus special 1.md delete mode 100644 Sunrise Special/1/Geheugen tellen.md delete mode 100644 Sunrise Special/1/Het rel file formaat.md delete mode 100644 Sunrise Special/1/Hybride programmeren.md delete mode 100644 Sunrise Special/1/MSX Assemblers.md delete mode 100644 Sunrise Special/1/Memman 2.3 intro.md delete mode 100644 Sunrise Special/1/Memman 2.3 specificaties.md delete mode 100644 Sunrise Special/1/Muis uitlezen.md delete mode 100644 Sunrise Special/1/Pointers in Pascal.md delete mode 100644 Sunrise Special/1/Recursief programmeren.md delete mode 100644 Sunrise Special/1/Rel assembleren.md delete mode 100644 Sunrise Special/1/Set scroll in basic.md delete mode 100644 Sunrise Special/1/Te zachte PSG bij de NMS 8250 55 80.md delete mode 100644 Sunrise Special/1/Track 0 op de turbo-r.md delete mode 100644 Sunrise Special/2/Cursus dd-graph.md delete mode 100644 Sunrise Special/2/Geheugen schakelen.md delete mode 100644 Sunrise Special/2/Interrupt service routines.md delete mode 100644 Sunrise Special/2/MSX-DOS 2 voor machinetaalprogrammeurs.md delete mode 100644 Sunrise Special/2/MSX-DOS 2.31.md delete mode 100644 Sunrise Special/2/Macro commandos met gen80.md delete mode 100644 Sunrise Special/2/Memman 2.42.md delete mode 100644 Sunrise Special/2/PCM Sampler.md delete mode 100644 Sunrise Special/2/PCM routines van de bios.md delete mode 100644 Sunrise Special/2/Pauze toets.md delete mode 100644 Sunrise Special/2/Programmeer taal c 2.md delete mode 100644 Sunrise Special/2/Programmeer taal c.md delete mode 100644 Sunrise Special/2/Rechtstreeks via PCM afspelen.md delete mode 100644 Sunrise Special/2/Stereo SCC.md delete mode 100644 Sunrise Special/2/VDP Cursus 1.md delete mode 100644 Sunrise Special/2/VDP Cursus 2.md delete mode 100644 Sunrise Special/3/De archeologie van de MSX.md delete mode 100644 Sunrise Special/3/De programmeertaal C deel 3.md delete mode 100644 Sunrise Special/3/De programmeertaal C deel 4.md delete mode 100644 Sunrise Special/3/File handles.md delete mode 100644 Sunrise Special/3/Getallen printen.md delete mode 100644 Sunrise Special/3/Hybride Call Commando's.md delete mode 100644 Sunrise Special/3/Memman problemen.md delete mode 100644 Sunrise Special/3/Programmeren sample chip.md delete mode 100644 Sunrise Special/3/Scrollen in kun basic.md delete mode 100644 Sunrise Special/3/TSR Change CPU.md delete mode 100644 Sunrise Special/3/TSR Development kit.md delete mode 100644 Sunrise Special/3/TSR Volume Input Meter.md delete mode 100644 Sunrise Special/3/Turbo Pascal Patch.md delete mode 100644 Sunrise Special/3/Turbo-R systeemcounter.md delete mode 100644 Sunrise Special/3/VDP Commando Registers.md delete mode 100644 Sunrise Special/3/VDP Cursus 3.md delete mode 100644 Sunrise Special/3/VDP Cursus 4.md delete mode 100644 Sunrise Special/3/Werken met ASCII C.md create mode 100644 future_disk/15/Looplichtje.md create mode 100644 future_disk/21/Ledjes.md create mode 100644 future_disk/21/Recursie.md create mode 100644 future_disk/27/Rotatie.md create mode 100644 future_disk/34/mathpack.md create mode 100644 future_disk/35/Datacompressie.md create mode 100644 future_disk/42/lijntjes.md create mode 100644 sunrise_special/1/r800.md create mode 100644 sunrise_special/2/Blinkmode.md create mode 100644 sunrise_special/2/Ledjes.md create mode 100644 sunrise_special/2/Resource.md create mode 100644 sunrise_special/2/cdd.md create mode 100644 sunrise_special/2/redirection.md create mode 100644 sunrise_special/3/Getdisk.md diff --git a/Future Disk/02/Cirkels in ML.md b/Future Disk/02/Cirkels in ML.md deleted file mode 100644 index 9f25fa8..0000000 --- a/Future Disk/02/Cirkels in ML.md +++ /dev/null @@ -1,173 +0,0 @@ -Cirkels in ML -------------- - -Cirkel = Zuiver Ronde Kring (Prisma Woordenboek p.61) - - -Vele wiskundige genie�n hebben hun hoofd gebroken (niet -letterlijk natuurlijk) over het fenomeen cirkel. Tegenwoordig -doen we niet meer zo lastig over cirkels. Je neemt gewoon je -rekenketel en berekent een aantal sinussen en cosinussen en -voila, een cirkel. - -Op een computer gaat het net zo. Je neemt basic, initialiseerd -een scherm en typt "CIRCLE (100,100),100,15". En wonderwel, er -wordt een cirkel op het scherm afgebeeld. - -Vraag: HOE DOE IK DIT IN ML. - -Antwoord: - -Om antwoord te geven op de vraag zou ik natuurlijk kunnen zeggen -dat je de computer moet gebruiken om een aantal sinus en cosinus -waardes te berekenen en deze vervolgens af te beelden. Hoe -bereken ik echter sinussen en cosinussen in ML. Natuurlijk -springen de wiskundigen onder ons een meter boven hun stoel uit, -want nu kunnen ze gaan zitten kwijlen over -machtreeksontwikkelingen (ja, zo smaakt het ook). Alle -wiskundigen hoeven nu dus niet meer verder te lezen, want zij -kunnen beginnen en h��l v��l geluk. - -Zo, nu zijn alleen de simpele zieltjes overgebleven (waaronder -ik) en kunnen wij het een stuk gemakkelijker aanpakken. - -Waar was ik gebleven, oh ja, cirkels. Om de simpelere oplossing -uit te leggen ga ik beginnen met te zeggen dat ik eigenlijk geen -hele cirkels ga berekenen. Niet gelijk schrikken, je zult het -verschil niet zien hoor. Met simpeler bedoel ik, dat ik maar -1/8ste deel van een cirkel ga berekenen en door een paar -spiegelingen de rest laat tekenen. Verder ga ik ook niet -oneindig veel punten berekenen (een cirkel bestaat theoretisch -uit oneindig veel punten), want dat is te veel werk. Nee, ik ga -gebruik maken van de maximale resolutie van de computer en -daardoor gaat het een stuk sneller. - -Om te beginnen laat ik een "flowchart" zien van de (overigens -niet zelf verzonnen) oplossing: - - +-------------------+ - | x=0 | - | y=R (straal) | - | A=R (hulp teller) | - +---------+---------+ - | -+------------------+ -| | -| + -| / \ -| / \ Nee -| < A----------------+ -| \ / | -| \ / | -| + | -| | Ja | -| +---------+---------+ | -| | y=y-1 | | -| | A=A+y+y | | -| +---------+---------+ | -| | | -| +-------------------+ -| | -| +---------+---------+ -| | Plaats 8 pixels | -| +---------+---------+ -| | -| +---------+---------+ -| | A=A-x-x-1 | -| | x=x+1 | -| +---------+---------+ -| | -| + -| / \ -| Nee / \ -+---------------< x>y > - \ / - \ / - + - | Ja - +---------+---------+ - | Klaar is Klara | - +-------------------+ - -Als we dit kunnen omzetten in ML dan zijn we klaar. Natuurlijk -wil iedereen weten hoe de oplosing werkt. Ik zal niet de -wiskundige afleiding geven, maar het op zijn "boerenfluitjes" -vertellen. - -We beginnen bovenaan de cirkel. Vervolgens trekken we een -horizontale lijn, en wel zolang tot er een punt buiten de cirkel -valt (dit wordt berekend met Pythagoras). Vervolgens gaan we de -lijn een pixel lager tekenen en begint alles van voor af aan. -Als dat niet simpel is en het werkt ook nog eens. Oh ja, voor de -grapjassen die na drie dagen nog aan het tekenen zijn: Stoppen -als x groter dan y is. Verder moet er rekening mee gehouden -worden dat het middelpunt van de cirkel ook de oorsprong van het -assenstelsel is (dat krijg je met wiskundige beschouwingen). - -En dan nu..... Geen cirkels natuurlijk, dat wil zeggen niet -hier, maar wel op de FUTUREDISK zelf. Er staan 3 files op de -FUTUREDISK die met cirkels te maken hebben. - -(1) Deze tekstfile (als je de FUTUREDISK tekstroutine zit, dan -kun je nu op de P drukken om de tekstfile te laten Printen). - -(2) De GEN file CIRCLE. Deze GEN file kun je in je eigen -programma's opnemen als CALL routine. De gebruiksaanwijzing -staat in de GEN file. - -(3) Een kleine demo met cirkels, die vanuit het software-menu -opgestart kan worden. - - -Nog een paar opmerkingen: - -(a) Nu iedereen weet hoe zij/hij (de dames niet vergeten) -cirkels moet maken in ML verwachten wij (ik in het bijzonder) -van de FUTUREDISK binnen enkele weken stapels diskettes te -ontvangen. Op deze diskettes staan dan uiteraard een heleboel -demo's waar cirkels worden getekend. Wat we ook ontvangen, we -zullen het zeker in een van de volgende nummers plaatsen. - -(b) De routine zoals ze in de GEN file staat is een trage -routine. Dit komt, omdat in de routine op het zogenaamde -klipping (buiten beeld vallen van pixels) gecontroleerd wordt. -Als je deze controle weg laat, dan wordt de routine aanzienlijk -sneller. - -(c) De credits voor het bedenken van deze oplossing gaan naar: - -Roland Waclawek - Kreisgenerator - c't 9/86 p.122 - -George Sutty & Steve Blair - Programmer's guide to the EGA/VGA - Brady Books, Simon & Schuster, New York, 1988 - -J�rgen Petsch - Kopierbahnhof VGA-RAM - c't 4/90 p.292 - -Foley, van Dam, Feiner & Hughes - Computer graphics: Principles and Practice - Addison-Wesley, 1990 - -J�rgen Petsch - Turbo-Circle: Schnelle Kreise in Turbo-Pascal! - c't 10/91 p.172 - - - -Voor vragen en/of opmerkingen bel: - - 043-437778 - - - - Groetjes, - - Jeroen "KUBIE" Smael - - - - C YA @ !!!!! diff --git a/Future Disk/02/Machinetaal 3.md b/Future Disk/02/Machinetaal 3.md deleted file mode 100644 index 76a6665..0000000 --- a/Future Disk/02/Machinetaal 3.md +++ /dev/null @@ -1,227 +0,0 @@ - - Machinetaal cursus deel III - - Welkom bij alweer het derde deel van deze cursus. - Zoals vorige keer beloofd beginnen we dit keer met de INC en - DEC commandos. - - Eerst een klein programmatje: - - ORG 0A000H - LD A,0 - INC A - LD B,255 - DEC B - RET - - Wat doet dit programaatje nu ? We zullen het even van regel - tot regel nalopen. - - ORG 0A000H - - Dit is een assembler instructie die de assembler zegt waar - in het geheugen het programma moet beginnen. In dit - voorbeeld dus op adres 0A000H - - LD A,0 - - Dit is een laadinstructie die we in de vorige cursussen al - behandeld hebben. Het register A wordt geladen met de inhoud - 0. - - INC A - - Aha, dit is dan eindelijk wat nieuws. - INC wil niets meer zeggen dan verhoog (van het Engelse - INCrease). Oftewel, het register A moet met 1 verhoogd - worden. Nu staat er dus in register A het getal 1. - - LD B,255 - - Laad het register B met 255 (in B staan dus nu alle bits op - 1). - - DEC B - - Ook weer een nieuwe instructie. - DEC is het tegenovergestelde van INC. DEC verlaagt dus de - inhoud van een register (van het Engelse DECrease). Nu staat - dus in register B het getal 254. - - RET - - Een instructie die wil zeggen dat het programma beeindigd is - en dat kan worden teruggekeerd naar het hoofdprogramma. - - De instructies INC en DEC kunnen op vele manieren gebruikt - worden en kent daarom een paar vormen. Deze zullen we effe - noemen: - (het nu volgende verhaal geldt voor zowel INC als DEC, in - het voorbeeld zullen we ons aan INC houden) - - INC m - - Verhoogt de door m te specificeren operand met 1. - - m kan zijn: r,(HL),(IX+d) of (IY+d) - - r staat voor alle achtbits registers, dus A,B,C,D,E,H,L - - (HL) betekent dat de inhoud van het adres waar HL naar - verwijst met 1 verhoogd moet worden. - - (IX+d) en (IY+d) willen zeggen, waar de inhoud van IX plus - de relatieve verplaatsing d met 1 verhoogd moet worden. - - INC ss - - verhoogt het door ss gespecificeerde registerpaar met 1 - - ss kan zijn: HL,DE,BC,IY,IX of SP - - Als je dus een INC op een 16-bits getal geeft, wordt ook - hier de inhoud met 1 verhoogt. - - - In het bovenstaande verhaaltje stonden een paar termen - waarvan je nog niets snapt (zoals (HL) of (IX+d)), maar die - zullen in de volgende cursussen nog wel worden uitgelegd. - - Je ziet INC en DEC zijn niet zo'n moeilijke instructies en - door er een beetje mee te spelen weet je al gauw hoe je ze - moet gebruiken. - - Ook vertelden we in de vorige cursus, dat we de JP en de - CALL zouden behandelen. Aangezien belofte schuld maakt, - - - JP en CALL-groep. - - JP en CALL zijn eigenlijk het beste te vergelijken met GOTO - en GOSUB in BASIC. Een CALL wordt, net zoals een GOSUB in - BASIC, afgesloten met een RETurn. - Uit een JumP kun je, eveneens als bij GOTO in BASIC, niet - met een RETurn of zoiets dergelijks terugkeren. - Het is dus al zoals de namen het zeggen: - een JumP staat voor spring (dus niet meer terug) - een CALL staat voor roep aan (en keer nog ooit eens terug). - - Om het allemaal een beetje te verduidelijken, dan nu een - klein listingkje. - - ORG 0A000H - - ST: - LD B,0 - CALL HEGEGA - RET - - HEGEGA: - INC B - RET - - Wat doet dit programma nu: - - ORG 0A000H - - zie boven. - - ST: - - Dit is een label (zie vorige cursus) - - LD B,0 - - Laad het register B met 0 - - CALL HEGEGA - - Roep de subroutine HEGEGA aan. - - RET - - Keer terug naar hoofdprogramma (bv BASIC) - - HEGEGA: - - Label subroutine. - - INC B - - Verhoog register B met 1. - - RET - - Keer terug naar hoofdprogramma (in dit geval dus naar de - instructie na de CALL). - - Dit programmaatje heeft dus niet meer gedaan dan B met 1 - verhoogd (Lees nog maar eens na dankzij onze nieuwe - textroutine, ook KUBIE is eens zo begonnen). - We zullen maar niet uitgaan leggen wat er hardware-matig - gebeurt als er een CALL of een JumP wordt uitgevoerd, want - dat zou helemaal onbegrijpelijk worden. - - In de volgende cursus zullen we een beetje meer MSX gerichte - machinetaal gaan behandelen, want het wordt nu toch wel heel - saai. - - Veel Succes namens: - - Ruud Gelissen en - Jan-Willem van Helden. - - --------Boekenlijst--------- - ZAKBOEKJE Z-80 - - J.B. Vonk -- Kluwer technische boeken -- (c) 1985 - - MACHINETAAL Z-80 - J.B. Vonk/E.J.J. Doppenberg -- Kluwer Tech. Boeken -- - (c) 1987 - - --------Woordenlijst-------- - - ADRES/GEHEUGENADRES/GEHEUGENPLAATS: - - Een plaats in het geheugen van de MSX. - - ASSEMBLER: - - Een programma dat het assembleren uitvoert. - - ASSEMBLEREN: - - Het omzetten van machinetaal naar MCODE. - Voorbeelden van machinetaal zijn de listingen in deze - cursus. - - BIT: - - Een waarde die 0 of 1 kan zijn. - (zie vorige cursussen) - - BYTE: - - Een groepje van 8-BITS. - (zie vorige cursussen) - - LABEL: - - Een naam voor een geheugenplaats, vergelijkbaar - met een regelnummer in BASIC. - - MCODE: - - Dit is de taal waarin de machinetaal commando's worden - omgezet en die de computer kan begrijpen en uitvoeren. - (zie vorige cursussen) - - REGISTER: - - Een register is te vergelijken met een variable - in BASIC. - (zie vorige cursussen) - - Voor vragen zie de Helplines. - diff --git a/Future Disk/03/Machinetaal 4.md b/Future Disk/03/Machinetaal 4.md deleted file mode 100644 index 2183774..0000000 --- a/Future Disk/03/Machinetaal 4.md +++ /dev/null @@ -1,221 +0,0 @@ -Welkom bij alweer de vierde aflevering van de - machinetaalcursus. - - Nadat we de vorige keren Z80 machinetaal behandelden - zullen we nu eens echt met MSX machinetaal beginnen. - - De eerste MSXjes hadden meestal 32 KROM en 16 KRAM tot - hun beschikking, in de latere modellen werd dit steeds meer. - De Z80 kan eigenlijk niet meer dan 64K tegelijk besturen. - Ho, zegt de Memorymapper bezitter : Wat moet ik dan met mijn - overige Krammetjes. Wel, luidt het antwoord, de Z80 kan niet - meer dan 64K TEGELIJK besturen, met behulp van slotschakeling - kan de Z80 veel meer geheugen aanspreken. - Aangezien het slotschakelen redelijk ingewikkeld is en voor - de beginnende programmeur niet echt nodig zullen we deze - techniek pas later behandelen maar nu de indeling van de - eerste 64K bespreken. - - De eerste 32K die bij het opstarten van je MSX door de - computer bestuurd worden zijn ROM. - ROM wilt zeggen Read Only Memory, geheugen dat alleen maar - door de computer gelezen kan worden. - Dit geheugen bevat de BASIC en de BIOS en kan niet door een - programmeur beschreven worden en loopt van &H0000 tot &H7FFF. - Het onderste gedeelte van het ROM (&H0000 tot &H3FFF) - bestaat uit BIOS en van &H4000 tot &H7FFF is BASIC. - - De tweede 32K, dus het geheugen van &H8000 tot &HFFFF, is - RAM. In dit RAM kan je dus je programma's kwijt. - Houdt er wel rekening mee dat op &H8000 BASIC programma's - bewaard worden en vanaf ongeveer &HE000 beginnen de - opslagarray's van BASIC en BIOS. - - Nu is dit natuurlijk allemaal leuk om te weten, maar wat heb - je d'er aan ???? - - Wel, de BIOS is een verzameling van routines die door de - ontwikkelaars van MSX geschreven zijn om het leven van de - MSX-er te vergemakkelijken. Als je elke chip met eigen - routines zou moeten aan spreken, zou je maanden aan het - programmeren zijn voor een "simpele" scroll demo of zo.. - - De BIOS bestaat dus uit een rij routines die allemaal hun - eigen werking hebben. - We zullen er een paar bespreken .... - - CHKRAM: - Adres: 0000h - Invoer: geen - - Deze routine reset de MSX en vult het geheugen met de - juiste beginwaarden (SCREEN 0 en zo..) - - CHGMOD - Adres: 005Fh - Invoer: A - - Deze routine zet de gewenste screenmode aan. - Wil je dus SCREEN 5 dan laad je A met 5 en roep je - CHGMOD aan. - - CHGET: - Adres: 009Fh - Invoer: geen - - Deze routine leest een teken van het toetsen bord. - Als er geen teken wordt ingedrukt wacht de routine - tot dit wel gebeurd. - - CHPUT: - Adres: 00A2h - Invoer: A - - Deze routine stuurt een ASCII teken naar het scherm. - In A moet dus de ASCII waarde van de letter, die je - wilt sturen staan. - - LPTOUT: - Adres: 00A5h - Invoer: A - - Deze routine stuurt een ASCII teken naar de printer. - Als het lukt om een teken te sturen zal de CARRY vlag - laag staan. Anders is de uitvoer mislukt. - - BEEP: - Adres: 00C0h - Invoer: geen - - Roep maar eens aan !!! En sta versteld van het - resultaat. - - GTTRIG: - Adres: 00D8h - Invoer: A - Uitvoer:A - - Met deze routine test je of er een vuurknop of de - spatie balk wordt ingedrukt. - De mogelijke waarden van A, bij de invoer kunnen zijn - - 0 spatiebalk - 1 1e vuurknop joystick (of muis) 1 - 2 2e " " " " " " 1 - 3 1e " " " " " " 2 - 4 2e " " " " " " 2 - - Bij het verlaten van de routine staan de volgende - mogelijkheden: - - 00h niet ingedrukt - FFh wel ingedrukt - - FORMAT - Adres: 0147h - Invoer: geen - - Deze routine doet hetzelfde als een _format in BASIC - - Met al deze wetenschap kunnen we nu natuurlijk enige - routines schrijven. - - ORG &HC000 - - CHGMOD:EQU &H5F - CHGET: EQU &H9F - CHPUT: EQU &HA2 - BEEP: EQU &HC0 - GTTRG: EQU &HD8 - CHKRAM:EQU &H00 - - LD A,0 - CALL CHGMOD - CALL CHGET - LD (PLACE),A - CALL CHPUT - LD HL,TEXT - LD (TXTPNT),HL - - LOOP: - LD A,0 - CALL GTTRG - JP NZ,EINDE - LD HL,(TXTPNT) - LD A,(HL) - CP "$" - JP Z,EINDE - LD (TXTPNT),HL - CALL CHPUT - CALL BEEP - JP LOOP - EINDE: - JP CHKRAM - TXTPNT: - DEFW TEXT - TEXT: - DEFM "Hallo Computeraartje. Je hebt net een " - PLACE: - DEFB 0 - DEFM " getypt. Als deze text je niet bevalt, " - DEFM "moet je op de spatie balk duwen. Als je dat" - DEFM " doet zal je MSX je op reset springen. " - DEFM "ZO, GENOEG TEXT ..... LATEN WE MAAR EENS " - DEFM "RESETTEN !!!!!!!!$" - - END - - Zo dat is dan de eerste keer dat we een grote routine - publiceren en het zal niet de laatste keer zijn .... - Deze routine wacht op invoer via de BIOS routine CHGET. - Hierna zal de routine beginnen met een tekst te printen. - - Boven de programmalisting staat een aantal maal EQU, - dit is geen commando maar en komt dus ook niet in het - geheugen te staan. - De assembler vervangt na deze reeks EQU's de labels die - ervoor staan door het getal erachter. - Wordt nu b.v een CALL BEEP gedaan voert de computer een - CALL &HC0 uit. - - Het CP commando in deze routine trekt vande inhoud van het - A register het Asciiteken $ af. Wanneer nu in A het - dollarteken komt, levert deze aftrekking nul op. - Het JumP Zero commando in de volgende regel zorgt er nu voor - dat er naar het LABEL : EINDE wordt gesprongen. - Door CP wordt de inhoudt van het A register niet veranderd. - - Hopelijk verdient de rest van de instructies geen uitleg, - anders bel je gerust de programmeer lijn maar eens. - ( zie helplines ) - - Zo, dank zij de terug blader optie kan je alles nog eens - mooi overlezen. Nu kun je eindelijk eens iets meer met je - MSX dan alleen maar optellen en zo.. - - In de volgende cursus zullen we nog wat instructies - behandelen en nog wat BIOS. Misschien beginnen we daarna wel - met de besturing van de VDP of de DISK-DRIVE in MCODE. - - In elk geval, - Veel succes namens: - Ruud Gelissen en - Jan-Willem van Helden - - - Als boeken raden wij aan: - - MSX-HANDBOEK VOOR GEVORDERDEN -- A.RENSINK -- KLUWER - TECHNISCHE - BOEKEN - - ZAKBOEKJE Z80 -- J.B.VONK -- KLUWER TECHNISCHE BOEKEN - - MACHINETAAL Z80 -- J.B.VONK/E.J.J.DOPPENBERG -- KLUWER - TECHNISCHE - BOEKEN - - ASCII TECHNICAL DATA-BOOK -- ASCII Systems Division -- - ASCII CORPERATION - - diff --git a/Future Disk/04/Machinetaal 5.md b/Future Disk/04/Machinetaal 5.md deleted file mode 100644 index 0515507..0000000 --- a/Future Disk/04/Machinetaal 5.md +++ /dev/null @@ -1,287 +0,0 @@ - - Machinetaal cursus deel 5 - - Na alle mooie informatie in de vorige afleveringen - gaven we jullie in de vorige aflevering (deel 4) de - eerste grote listing. Gelukkig klopt onze programmeer - cursus tot hier toe nog helemaal want we hebben nog geen - boze reacties via onze programmeer-lijn gehad. - - Overigens excuses voor de nogal snelle behandeling van - EQU en CP, de schrijver van het stukje (JWVH) had niet - gecontroleerd of alle gebruikte commando's in de listing - behandeld waren. Daar Ruud Gelissen het stuk pas op de - clubdag in Elsloo te zien kreeg (de deadline dus) is er - toen snel nog enige tekst toegevoegd. We hopen dat dit - in de toekomst niet meer voorkomt (red.). - - Vanwege bovenstaand verhaal behandelen we EQU en CP nog - een keer, maar nu wat uitgebreider. - - EQU: - - EQU is niet de nieuwe Europese munteenheid, maar de - betekenis is wel bijna hetzelfde. In het Engels betekent - het namelijk ,"maak gelijk aan" (EQUate). Voor de munten - betekent dat dus dat ze gelijk gemaakt worden aan een - standaard, voor de computer betekent dat, dat het - ervoor staande LABEL overal in de listing vervangen - wordt door het achter de EQU staande cijfer. - - Voorbeeld: - - KOEN: EQU 6 - DOLS: EQU 3 - - LD A,KOEN - LD B,DOLS - ADD A,B - RET - - KOEN wordt nu overal vervangen door 6, - DOLS wordt nu overal vervangen door 3, dus in het - geheugen zal staan: - - #3E,#6 ; LD A,6 - #05,#3 ; LD B,3 - #80 ; ADD A,B - #C9 ; RET - - Je ziet, EQU is geen commando en wordt dus niet in het - geheugen geplaatst. - - P.S. het teken "#" is hetzelfde als "&H" en betekent - dus dat de hexadecimale notatie wordt gebruikt. - Sommige assemblers maken gebruik van het "#". - - CP: - - CP staat voor het Engelse ComPare, wat vergelijk - betekent. Het vergelijkt de inhoud van de Accumulator - (register A) met die van de waarde die achter de - instructie staat en zet aan de hand van de uitkomst de - vlaggen. CP 251 trekt dus 251 van A af maar zet de - uitkomst niet terug in A. Als A nu gelijk aan 251 is, - is de Z vlag geset ( 1 dus ) en de C vlag niet ( ** ). - Is A kleiner dan 251, dan is de C vlag geset, de Z vlag - niet. Is A groter dan 251, is de Z vlag gereset en de - C vlag ook. - - ** : De C vlag of CARRY vlag wordt dus geset als een - berekening een "foutje" opleverde. - b.v. LD A,100 of: LD B,255 - SUB 110 INC B - - of: LD A,#10 (=16) ect. - CP 17 - (voor een overzicht van de vlaggen zie FUTURE-DISK #0 - (public domain)). - - Nu het complete overzicht van CP: - - CP s - - Trekt de door s te specificeren operand af van de inhoud - van de accumulator. Het resultaat wordt genegeerd maar - beinvloed wel de vlaggen. - - s kan zijn: r,n,(HL),(IX+d) of (IY+d) - - r: - De accumulator wordt vergeleken met een van de registers - of met zichzelf. - r kan dus zijn: A,B,C,D,E,H of L - - n: - Een getal varieerende van 0 to 255. - - (HL): - Met de inhoud waarheen het adres HL verwijst. - - (IX+d): - Met de inhoud waarheen het adres IX plus verplaatsing d - verwijst. - - (IY+d): - Met de inhoud waarheen het adres IY plus verplaatsing d - verwijst. - - Oke, dit stukje is gedeeltelijk overgeschreven uit het - zakboekje Z80 Machinetaal door J.B.Vonk, omdat het - hierin het duidelijkst en goed beschreven staat. Dit - even voordat andere instanties hierover problemen gaan - maken ! - - - Al eerder zijn de POINTER register genoemt maar nog - niet uitvoerig besproken. - - IX en IY - - IX en IY zijn bijna gewone 16-bits registers als DE en - BC, ware het niet dat zij nog een speciale functie - hebben. Je kunt bijvoorbeeld register A laden met - (IX+10). Nu komt in A de inhoud van geheugenplaats 10 na - het adres waar IX naar verwijst. Het klinkt moeilijk, - maar kijk eens naar dit voorbeeldje. - - LD IX,TRASH - LD A,(IX+0) - TRASH: - DB 0 - DB 1 - DB 2 - DB 3 - - Nu komt in A dus 0 te staan. Vervangen we nu LD A,(IX+0) - door LD A,(IX+1), dan komt er in A 1 te staan. IX wordt - daarom altijd aan geduid met de verplaatsing d (IX+d). - d kan een waarde van 0 to 255 aannemen. - - Dit gehele verhaal geldt ook voor IY. - - Ook zagen we een aantal keer (HL). Dit is te vergelijken - met (IX+0). - - Met deze instructies kunnen we ook INCreasments en - DECreasments uitvoeren. INC (IX+143) is dus gewoon - mogelijk. Dit opent veel nieuwe mogelijkheden voor - professionele programmeurs (Databases,spreadsheets etc.) - Voor de demo en spelletjes programmeur zijn ze niet zo - interessant vanwege hun traagheid. Het INCreasen - (taalverloedering) van A duurt 4 T-cycli (computertijds - eenheid). INC (HL) duurt 11 T-cycli en INC (IX+d) duurt - maar liefst 23 T-cycli (bijna het 6 dubbele van INC A). - Dit wil natuurlijk niet zeggen dat je ze niet moet - gebruiken. Soms zijn ze onmisbaar, zoals in muziek - routines, want wil je het anders schrijven, kost het je - veel en veel meer geheugen. Zo zie je maar, vaak is - programmeren een kwestie van kiezen tussen snelheid of - geheugen besparing. - - P.S. traag moet hier eigenlijk tussen "aanhalings- - tekens" staan, een computer commando is nooit echt - traag. - - Een T-cycli is 1 puls van de ingebouwde klok van de - processor: Op de Z80 is dat 4 Mhz (afgerond). - 1 T-cycli duurt dus 1/4*10e6 = 2,5*10e-7 = 250 nanosec. - - Op de Turbo R draait het interne klokje met een snelheid - van 28 Mhz. Hier duurt 1 T-cycli dus 1/28*10e6 = - 3,5*10e-8 = 35 nanosec. (dat is snel !!!, dat lijkt ... - wel !!!). Maar dit is allemaal een beetje al te - technisch, want zodadelijk beginnen we over zaken die - wij niet snappen... (zoals interne struckturen of - zoiets). - - De Z80 kent ook nog de logische instructies. - Voor de vergevorderde BASIC programmeur zijn ze - misschien al bekend, maar voor het gros van de MSX-ers - is het Latijn (of Chinees voor de Latinisten). - - Het zijn: OR,XOR en AND. - - De officieele notatie is OR s, waarbij s hetzelfde kan - zijn als bij CP (zie boven). - - OR B voert een OR uit op A met de inhoud van B en zet - het resultaat in A. De logische functies vergelijken 2 - getallen binair bit voor bit met het volgende resultaat. - - A 0101 0101 - s 1001 0111 - - A OR s 1101 0111 - De OR(of) functie maakt een bit 1 als in A of in s er 1 - staat of als ze beide 1 zijn. - Voor AND(en) geldt dat beide bits 1 moeten zijn wil de - uitkomst 1 zijn. - - A 0101 1110 - s 1001 0110 - - A AND s 0001 0110 - - De XOR (eXclusive OR) doet hetzelfde als OR, maar niet - als beide bits 1 zijn. - - A 1001 0101 - s 0110 1110 - - A XOR s 1001 1011 - - Met deze instructies kun je bits testen, of setten. - Let op: XOR A geeft 0 (kijk maar na!) - XOR 255 Inverteer A - - Voor iedereen met Natuurkunde in zijn pakket of op - school, dit allemaal gaat ook behandeld worden als - onderdeel van fysische informatica. Door er nu al mee om - te gaan is het dan gemakkelijker te begrijpen. - - Om bits te setten of resetten zijn er ook de - instructies: - - SET en RES - - SET b,m - - Set het door b te specificeren bit van de door m te - specificeren operand. - m kan zijn: r,(HL),(IX+d) of (IY+d). - - SET 1,A - - Bit 1 van register A staat nu op 1. - - Bij RES geldt natuurlijk het omgekeerde. De bits worden - nu op 0 gezet. - - Nog een listinkje to slot: - - ORG #A000 - - XOR A ; in A staat 0 - LD B,A ; in B ook - LOOP: - DEC A ; A wordt verlaagd (*) - INC B ; B wordt verhoogd - JP NZ,LOOP ; in A en B staat 0 - SET 3,A ; in A staat %0000 1000 - SET 5,B ; in B staat %0010 0000 - OR B ; in A staat %0010 1000 - LD C,A ; in C staat %0010 1000 - LD A,B ; in A staat %0010 0000 - AND C ; A AND C - LD (GENIC),A ;in ZOOI komt %0010 0000 - RET ; terug naar ?? - GENIC: - DB 0 - END - - Opmerking: # en % staan voor resp. Hexadecimaale en - Binaire getallen. - - *: Als nul verlaagd wordt met 1 wordt het 255 (de - routine voert dus 256 x deze loop uit). - - De listing slaat natuurlijk nergens op, maar we hopen - dat je de logische functies hierdoor een beetje beter - begrijpt. - - Volgende keer wordt het misschien eens tijd voor een - scroll of zoiets, want nu zijn alle basis begrippen - besproken. - - Veel succes en plezier namens: - Ruud Gelissen - Jan Willem van - Helden. - - Met dank aan: - Zakboekje Z80 J.B. Vonk - Machinetaal Z80 J.B. Vonk en - E.J.J. Doppenberg - - diff --git a/Future Disk/05/Machinetaal 6.md b/Future Disk/05/Machinetaal 6.md deleted file mode 100644 index d16ebb6..0000000 --- a/Future Disk/05/Machinetaal 6.md +++ /dev/null @@ -1,168 +0,0 @@ - Welkom bij machinetaal cursus deel 6. - - Wat zullen we vandaag weer eens vertellen. - Voorstel van R.G.: Hoe werkt basic - J.W. : NEEEEEE ! - R.G. : De stack ? - J.W. : vooruit dan maar. - - Het SP-register (STACK-POINTER). - - Kort samengevat zou je het SP-register kunnen aanduiden - als een register dat de plaats in het geheugen aangeeft - waar allerlei adressen worden opgeslagen. - Wat gebeurt er nu eigenlijk als je een CALL geeft ? - Eerst wordt het adres waar SP heen verwijst gevuld met - het adres waar bij een RET heen moet worden teruggekeerd, - dan wordt het SP-register verlaagd met 2, zodat het het - een nieuw adres aangeeft waar bij een nieuwe CALL het - adres weer kan worden opgeslagen, uiteindelijk wordt een - JP naar het te CALLen adres uitgevoerd. - - Het SP-register kan ook worden gebruikt voor het opslaan - van andere registers, waarvan men later de waarde weer - nodig heeft. - - Een PUSH HL zorgt er bijvoorbeeld voor dat de inhoud van - HL wordt opgeslagen in de geheugenplaats waarheen SP - wijst. M.B.V een POP HL wordt deze inhoud weer herstel - naar zijn oude waarde, maar een PUSH HL en een POP DE - mag ook best, zo kan men dus gemakkelijk HL in DE - "overladen". - - Pas altijd een beetje op met het gebruik van SP ! - Laat een stapel (STACK) nooit te veel groeien, de stapel - wordt van boven af naar beneden in het geheugen opgebouwd - en wijst bij het opstarten van je MSX meestal de boven- - grens van het vrije geheugen aan (ergens in de #Fxxx, - hangt af van b.v. het opstarten met of zonder CTRL-toest - ingedrukt ); zou je nu een programma maken waarbij niet - elke CALL wordt afgesloten met een RET zou deze stapel - steeds lager in het geheugen terecht komen en b.v je - programma kunnen overschrijden........ - - Let er bij het gebruik van SP verder nog op dat het - laatste op de stapel gekomen getal/adres er het eerste - er weer afgaat, programmeer dus zo : - - PUSH AF - PUSH HL - PUSH DE - PUSH BC - PUSH IX - PUSH IY - - POP IY - POP IX - POP BC - POP DE - POP HL - PUSH AF - - P.S. Dit zijn alle mogelijke vormen van PUSH en POP. - P.P.S Je ziet wel dat m.b.v een PUSH AF ook de - vlagstatus wordt opgeslagen. - P.S.S.S.De STACK wordt in BASIC o.a. gebruikt voor het - opslaan van terugkeeradressen bij een GOSUB - - TIP: - Wil je er zeker van zijn dat de stapel bij b.v. de - terugkeer naar basic weer zijn oude waarde heeft (het - adres waar basic wordt gestart) gebruik dan: - - LD (STACK),SP ; aan het begin - LD SP,(STACK) ; aan het einde - STACK: DW 0 - - - Het R-Register.(Refres-Register) - - Het R-register is een soort klokje dat razensnel tot 128 - telt en dan weer overnieuw vanaf nul begint. - Je kunt R maar op 2 manieren gebruiken : - - 1. LD A,R - 2. LD R,A - - R kan dienen als RANDOMIZER m.b.v LD A,R krijg je in A - in soort RANDOM getal, let wel op dat bit 7 altijd nul is - , wil je b.v. in A een RANDOM kleur gebruik je : - - LD A,R - AND %00001111 - - In A staat nu een willekeurig getal van 0 to 15. - - Hooks. - - Letterlijke vertaling luidt : HAKEN en deze benadert - redelijk de betekenis. - Een HOOK is een opeenvolging van 5 bytes in het RAM die - normaal allemaal met RET (#C9) gevuld zijn. - Deze "RAMHAKEN" zijn speciaal voor de programmeur - toegevoerd aan het werkgeheugen van BASIC en worden - aangeroepen op verschillende tijdstippen, afhankelijk - van de HOOK. - - Als we nu die 5 bytes vervangen door andere waardes kan - de hook plotseling iets anders gaan doen dan alleen maar - te RETten, je zou er b.v. een JP naar een ander adres in - het geheugen kunnen zetten waar je eigen routine begint, - of een JP naar een BIOS routine. - - Een voorbeeltje: - De ROM-routine die een teken op het scherm zet (CHPUT) - , geeft een CALL naar de HOOK op #FDA4 in het geheugen. - Stel nu dat je alle tekens die op het scherm komen ook - naar de printer wil sturen, de BIOS-routine die een - teken naar de printer stuurt is #A5 (LPTOUT). - Je kunt dit dus doen door in de HOOK een JP naar #A5 te - zetten. - Het JP commando bestaat uit 3 bytes. - 1. #C3 voor de computer aan te geven dat er een JP gaat - plaats vinden. - 2. #xx waarbij xx staat voor het lagere deel (!) van het - adres waar naartoe gesprongen gaat worden - 3. #xx waarbij xx staat voor het hogere deel van het - adres waar naartoe gesprongen gaat worden. - Een JP naar #00A5 moet dus zo in het geheugen gezet - worden: #C3 #A5 #00 - M.b.v het volgende programma kan de HOOK dan worden - "omgebogen": - - LD A,#A5 - LD (#FDA4+1),A ; of #FDA5 - XOR A ; = LD A,0 allen sneller - LD (#FDA4+2),A - LD A,#C3 - LD (#FDA4),A - RET - - Je ziet dus dat je het beste als laatste het #C3 - commando kunt geven, omdat anders de HOOK misschien nog - aangeroepen kan worden voordat je het juiste adres hebt - neergezet en de computer dan een JP #C9C9 zou uitvoeren. - - Tot zover deze machinetaalcursus, volgende keer zullen - we je o.a. uitleggen hoe het INTERUPT-systeem van je MSX - in elkaar zit en hoe je dit m.b.v. een HOOK kunt - gebruiken voor talrijke doeleinden. - Nu zullen je we alleen nog even zeggen welke HOOKs je - hiervoor kunt gebruiken: #FA9A of #FD9F (je ziet 5 bytes - verder in het geheugen. - Een andere HOOK die we nog even wilden noemen is: - #FDD1, die wordt aangeroepen aan het begin van de - routine die enkelvoudige toetsaanslagen verwerkt. - M.b.v. deze HOOK kun je b.v. een toetsaanslag voor een - ander doeleinde gebruiken. - - Dat was het dan weer (ja, ik begin nu niet weer met een - heel verhaal onder het motto: dat wilden we nog even - zeggen Jan-Willem.), niet meer deze keer. - - Veel programmeerplezier : Jan-Willem van Helden - Ruud Gelissen. - - p.s. leest iemand ooit deze tekst ? - - diff --git a/Future Disk/05/Special Effects BASIC.md b/Future Disk/05/Special Effects BASIC.md deleted file mode 100644 index e7a92f3..0000000 --- a/Future Disk/05/Special Effects BASIC.md +++ /dev/null @@ -1,216 +0,0 @@ - SPECIAL EFFECTS BASIC - -------- # 1 -------- - - Dit keer nog een soort cursus, niet over het gewone huis,tuin - en keuken BASIC, maar over het BASIC met wat verdere - bedoelingen: spellen, demo's, gebruikersprogramma's, enz. - enz. - - De naam special effects klinkt nog al proffesioneel. Het is - dus niet een cursus over de comando's PRINT, CLS, SCREEN .. - enz. Ik wil het dan ook in deze eerste aflevering hebben over - het zelf maken van letters (en natuurlijk gebruiken in eigen - programma's) en kleuren. - - LETTERS - ------- - - Om de letters op het beeld te printen kun je gebruik maken - van : - - SCREEN 5 : OPEN"GRP:"AS#1 : PRINT#1,"" - - Dit is een standaard comando dat bijna iedereen kent. Maar - als je nu zelf letters wilt gaan maken, in een tekenprogramma - of gewoon in basic, is dat een stuk moeilijker op het beeld - te printen. Je hebt hierbij een paar comando's nodig : - - A=LEN(A$) : In A komt de lengte van A$ te staan. - Bijvoorbeeld : A$="FUTURE" dan is A 7. - - A$=MID$(B$,A,B) : In A$ komt te staan : de lengte B, A - posities ver, van B$ . - Bijvoorbeeld: B$="FUTUREDISK 5",A=7,B=4 - dan staat in A$ "DISK". - - A=ASC(A$) : In A komt de ASCII waarde van A$ te staan. - Als de lengte van A$ (LEN(A$)) > ��n, - dan komt in A de ASCII waarde van de eerste - letter te staan.Dus als A$="FUTUREDISK" is - dan staat in A 70 (de ASCII waarde van "F") - - SET PAGE A,A : Wisselt van pages.In A staat het - PAGENUMMER.(geldt alleen voor screen 5 en - hoger.) - - COPY(A,B)-(C,D) : Met dit comando copi�er je van A,B tot C,D - ,G TO (E,F),H,AC uit page G naar E,F uit page H. - i.p.v AC (Ander Commando) moet je : - - PSET,PRESET,XOR,OR,AND,TPSET,TPRESET,TXOR,TOR,TAND - - zetten. Wat al deze commando's betekenen, - ga ik nu niet uitleggen.(Kijk maar eens in - het boek dat bij de computer zit onder het - hoofdstuk LOGISCHE OPERATIES). - De functie van de z.g.n LOGISCHE OPERATIES - achter een COPY invoer is dat je iets over - elkaar kunt copi�ren zonder dat hetgene - waar je overheen copi�ert weg gaat. - - Nu maar eens een programma : - - 10 color 15,0,0:screen5 :'maak altijd de achtergrond 0! - 20 set page 1,1: close: open"grp:"as #1 - 30 preset (0,0):print #1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - 40 set page 0,0 - 50 a$="FUTUREDISK ISSUE VIJF" - 60 for a = 1 to len(a$) - 70 b$= mid$ (a$,a,1) - 80 b= asc (b$) - 90 b=b-65 : b=b*8 - 100 copy(b,0)-(b+7,8),1 to (c,d),0 - 110 c=c+8 : next a - 120 goto 120 - - Regel 90: De ASCII waarde in B is altijd groter dan 64 (65 = - ASCII waarde "A") De "A"-"Z" in page 1 staan op positie 0,0. - Als je dus de letter A uit page 1 wilt copi�ren, moet B met - 65 worden afgetrokken.Maar als je "B" wilt copi�ren, krijg - je de positie 1,0 , terwil de "B" op 8,0 staat.Er moet dus - met 8 vermenigvuldigd worden. - - Regel 110 : Als je van C een constante zou maken, zouden - alle letters uit A$ op een plaats dus overelkaar gecopi�erd - worden.Dit is niet de bedoeling dus moet C iedere keer met 8 - (de lengte van een letter) worden opgeteld. - - De letters uit dit programma zijn standaard. Je kunt zelf ook - letters tekenen in een tekenprogramma. Je kunt ook andere - afmetingen gebruiken , dan is een kleine wijziging nodig. - Maar als echte BASIC programmeur wil je zelf letters in BASIC - maken. - We gaan nu dikke letters met 7 verschillende kleuren maken. - Het principe berust hierop: zet 7 keer de letters A-Z onder - elkaar, steeds met een andere kleur.Als je nu de tweede - lijn van de tweede regel op de tweede lijn van de eerste - regel copi�ert en de derde lijn van de derde regel op de - derde lijn van de eerste regel copi�ert ENZ.ENZ., krijg je - in de eerste regel 7 verschillende kleuren. - Als je ze nu deze eerste regel dikker wilt gaan maken, - gebruik je het bovenstaand beschreven commando - COPY(A,B)-(C,D),G TO (E,F),H,TPSET (in dit geval TPSET, - want dit "achtervoegsel" zorgt dat je iets over elkaar heen - kunt zetten, zonder dat hetgene waar je overheen copi�ert - weg gaat.) Dit is ideaal, want we willen de eerste regel - over de eerste regel heenzetten, ��n positie verder.(Dit is - het principe van letters dikmaken.) We doen dus : - - COPY(0,0)-(254,8),1 TO (1,0),1,TPSET - - In een programaatje wordt dit alles : - - 10 color 1,0,0 : screen 5 - 20 set page 1,1 : open"grp:" as #1 - 30 fora=0to7:preset (0,a*8):?#1,"ABCDEFGHIJKLMNOPQRSTUVWXYZ" - 40 color a+2:next a - 50 fora=0to7:copy(0,a*8+a)-(255,a*8+a)to(0,a) - 60 next a - 70 'letters in regel 1 hebben 7 kleuren - 80 copy(0,0)-(254,8) to (1,0),,tpset - 90 'letters in regel 1 dikker gemaakt - 100 'laad nu vorige programma en doe dan SCREEN5 : GOTO 40 - - Als U nu denkt van "Moet ik dat nu allemaal gaan intypen" dan - heeft U het mis. Op deze diskette staat het programma - BASICKS1.LDR . Als u dit runt, ziet U alle voorbeelden die - hier besproken worden. - - KLEUREN - ------- - Als U nu de kleuren van de letters niet mooi vindt, kunt U - die veranderen met : - - COLOR=(A,B,C,D) : A = kleurnummer (0-15) - B = tinten rood (0-7) - C = tinten groen (0-7) - D = tinten blauw (0-7) - - Als je bijvoorbeeld bij de vorige programma de kleuren 1-7 - hebt gebruikt en je wilt ze laten vari�ren van donker naar - licht rood (bijvoorbeeld) dan doe je dus : - - FOR A = 1 TO 7 : COLOR = (A,A,0,0) : NEXT A - - (de kleur en de kleur tint zijn het zelfde dus kun je twee - keer A gebruiken want : color 1 heeft 1 tint rood , color 2 - heeft 2 tinten rood enz.) - - Dit is wel leuk maar er zijn veel leukere dingen te doen.Ik - zal 3 programa's bespreken. - - ZEEPBEL - ------- - In het programma worden er met het commando RND gewerkt. - - A=INT(RND(B)*C) : In A komt : Random van B (Random is - willekeurig) Als B dus 1 bevat krijg je - allemaal willekeurige getallen van 0 tot 1 - In C komt een getal te staan dat aangeeft - hoeveel getallen er mogelijk zijn. INT - betekend gewoon afronden op het - dichtsbijliggende natuurlijke getal. - Als B=1 en C=10 dan staat in A een - willekeurig getal van 1 tot en met 10. - - In ZEEPBEL worden 15 cirkels getekend op met RND bepaalde - co�rdinaten met RND bepaalde tussenruimte.Iedere cirkel heeft - een kleur van 1-15 (0 = achtergrond). De kleinste cirkel - heeft kleur 1, de �nerkleinste kleur 2 enz. - Als je nu alle kleuren 0,0,0 maakt (zwart en gelijk aan - achtergrond) dan zie je dus niets. Als je nu kleur 1 wit - (7,7,7) maakt en de rest zwart, dan kleur 2 wit en de rest - zwart , dan kleur 3 wit en de rest zwart enz. enz., dan - zie je dus dat er als het ware een cirkel naar voren komt.Als - je nu van kleur 15 naar kleur 1 springt dan lijkt het net als - of de cirkel kapot springt (het ZEEPBEL effect). - (ZEEPBEL en de twee volgende programma's staan ook in - BASICKC1.LDR) - - FUTUREDISK INTROLOGO - -------------------- - - Dit programmaate bootst de intro van (deze) FUTUREDISK na. - De intro met het rollende licht wel te heten. De tekening - staat in een .DAT file en deze laden we in in PAGE 1. - We maken nu alle kleuren (0 uitgezonderd) donkerblauw (0,0,1) - Dit kan door : - FOR A=1 TO 15 : COLOR =(A,0,0,2) : NEXT A - - Dan wordt de tekening uit PAGE 1 gecopi�rt naar PAGE 0 en - wordt net als bij ZEEPBEL eerst kleur 1 wit gemaakt en kleur - 2-15 donkerblauw enz.Doordat BASIC in dit programma nog al - snel functioneerd krijg je een soort Machine Taal effect. - - - COUNT - ----- - - In het laatste programma COUNT wordt afgeteld van 9 tot 0. - We laden ook hier weer een .DAT file in. Alle kleuren worden - zwart gemaakt en het aftellen begint.Als U spatie drukt , - komt het 2e deel van COUNT. Nog een keer wordt er afgeteld , - nu in digitale cijfes. - - Zo zie je maar weer dat je met een simpel commando als COLOR - =(A,B,C,D) leuke programaatjes kunt maken.Ik hoop ook dat ik - de ANTI-BASICers een beetje heb kunnen overtuigen dat BASIC - niet alleen iets is voor domme zielepootjes. Grote spellen - zullen inderdaad niet snel genoeg werken in basic (zonder - R800), hier heb je toch Machinetaal voor nodig. - - In de volgende SPECIAL EFFECTS BASIC zal ik aandacht besteden - aan SPRITES en er zullen ook weer de nodige programma's bij - zitten. Ik hoop dat het leerzaam was. Volgende keer meer! - - Tom Wauben diff --git a/Future Disk/06/Machinetaal 7.md b/Future Disk/06/Machinetaal 7.md deleted file mode 100644 index b46b1f1..0000000 --- a/Future Disk/06/Machinetaal 7.md +++ /dev/null @@ -1,203 +0,0 @@ - - Machinetaal Cursus Deel 7 - - Hoera, 1 jaar FutureDisk. Dat betekent ook 1 jaar de - machinetaal cursus. We hopen dat je er iets aan gehad - hebt en nu toch al een beetje gevorderd bent. - - Deze aflevering bekijken we eens de interrupt hook. - - In BASIC bestaat het commando "ON INTERVAL GOSUB". Dit - commando zorgt ervoor dat er om een bepaalde tijd naar - een programma stukje gesprongen wordt en het hoofd- - programma onderbroken wordt. Na afhandeling van de - routine wordt het hoofdprogramma weer aangesproken - totdat er weer een INTERVAL optreed. - - Nu in machinetaal is het ook niet anders. Alleen bestaan - er hier geen commando's voor. We geven even een - voorbeeld. - - Stel je wilt een scroll die voortdurend doorgaat (De - PLUTO demo) of een muziekroutine die regelmatig speelt. - Door nu op #FD9F een JP (jouw routine) te zetten kun je - er zeker van zijn dat om de 50/60 seconden (hangt af van - je interruptfrequentie) deze routine wordt aangegeven. - - Een voorbeeldje om een routine op interrupt te zetten: - - LD A,#C3 ;de JumP instruktie - LD HL,CODE ;jouw routine adres - DI ;zet de interrupt uit ! - LD (#FD9F),A ;plaats op H_TIMI - LD (#FDA0),HL ;plaats op H_TIMI+1 - EI ;Enable Interrupt - - Na de EI zal je programma bij elke interrupt naar je - routine springen (het adres CODE). - - Ook bestaat de H_KEYI, #FD9A nog. Hook #FD9A wordt veel - vaker aangeroepen dan H_TIMI (precieze frequentie - onbekend). Deze hook moet je dan ook gebruiken voor - screensplits etc. Voor muziekroutines, scrolls e.d. - gebruik je gewoon H_TIMI. - - Deze beide hooks zijn allebei uit te schakelen door het - gebruik van DI (Disable Interrupt) en in te schakelen - door EI (Enable Interrupt). - Zodra de MSX een interrupt krijgt (de Z80 zorgt hiervoor - ) springt de computer naar adres #38. Normaal staat hier - BIOS en worden dus H_KEYI en H_TIMI afgehandeld. - Gevorderde programmeurs schakelen echter de BIOS weg - (ANMA bijvoorbeeld) en plaatsen op #38 hun eigen - interrupt afhandeling. Omdat RAM sneller is dan ROM zijn - er nu enkele mogelijkheden meer want de ROM afhandeling - is nogal erg traag. Maar dit soort truuks zijn alleen - nodig als je een megademo met vele screensplits, - line-interrupts etc. wilt maken. Maar dat is voor de - gevorderde. - - Nu dacht men eind jaren '70 bij Zilog inc. dat er - behoefte was aan meerdere interrupt modes namelijk: - - Interrupt Mode 0 (IM0) - Na een interrupt-aanvraag wacht de Z80 tot het - randapparaat een instructie op de databus plaatst. Deze - instruktie wordt uitgevoerd. Een CALL of RST geeft een - sprong naar een subroutine die met RETI moet worden - afgesloten. - Deze interrupt mode heb ik nog nooit gebruikt en ik - twijfel dan ook sterk of die ook wel in het MSX systeem - ondersteund wordt. Wie het weet mag bellen. - - Interrupt Mode 1 (IM1) - De Z80 geeft een RST #38 (call #38). Dit is dus de - normale interrupt mode waarop de MSX standaard staat. - - Interrupt Mode 2 (IM2) - (er staat in m'n boekje een lap tekst van 10 regels met - onbegrijpelijke taal. Aangezien ik deze Interrupt Mode - ook nog nooit heb zien worden toegepast plaats ik dit - verhaal niet. Voor geinterreseerden: Koop een boek over - de Z80). - - Al deze modes zijn te schakelen met de commando's IM0, - IM1 en IM2. - - Ook genereert de Z80 nog een nietmaskeerbare interrupt - (NMI). Een interne flipflop wordt gereset bij de - aanvraag van een NMI. Na elke instructie wordt deze - getest. Bij een positief springt de Z80 naar adres #66. - In de normale BIOS staat hier de afhandeling voor het - MSX systeem. - Ook bestaat de BUSREQUEST, maar die wordt op MSX niet - ondersteund. - - Zo nu weet je toch wel alles wat er aan interrupts op de - MSX te vertellen valt. Ruud had vorige keer de overige - Hooks al beschreven, dus daar verwijs ik graag naar. - - Tot slot nog een voorbeeldje: - - DB #FE ;Header voor GEN80 - DW ST,EN,ST ;(bij WBASS2 niet nodig) - - ORG #C000 -ST: - LD HL,#FD9F ;oude Hook bewaren - LD DE,HOOKST - LD BC,5 - LDIR ; zie uitleg onder - LD A,#C3 - LD HL,INTERR ;nieuwe Hook neerzetten - DI - LD (#FD9F),A - LD (#FDA0),HL - EI - LOOP: - XOR A - CALL #D8 ;wachten op spatie - JR Z,LOOP ;NZ is spatie - - RESINT: - LD HL,HOOKST - LD DE,#FD9F - LD BC,5 - DI - LDIR ;herstel hook - EI - RET - INTERR: - LD HL,(TXTPNT) - LD A,(HL) - CP "@" - CALL Z,ENDTXT ;kijk einde tekst - INC HL - LD (TXTPNT),HL - JP #A2 ;Print ASCII waarde(BIOS) - ;(de RET aan het einde - ; van deze routine keert - ; van de interrupt terug) - ENDTXT: - LD HL,TEXT - LD (TXTPNT),HL - LD A,(HL) - RET - HOOKST: - DS 5 ;opslag hook - TXTPNT: - DW TEXT ;Pointer - TEXT: - DB "Hallo Boppers, dit is een voorbeeld van" - DB "een tekst die eeuwig doorgaat totdat je" - DB "op de spatiebalk ramt. Dit staat op in-" - DB "terrupt. Voor meer info zie de Future " - DB "Disk.......... Vaarwel Moeder !@" - EN: END - - Uiteraard zijn wij niet verantwoordelijk voor de - gevolgen van bovenstaande tekst. - - Het enigste nieuwe commando dat we hier gebruikt hebben - is het LDIR commando. - M.b.v. dit commando kan men gemakkelijk delen van het - geheugen kopieren. - De officiele uitleg is : - - LDIR: LoaD Increment Repeat - Laadt de inhoud van de geheugen locatie waarnaar - registerpaar HL wijst in de geheugenlocatie - waarnaar registerpaar DE wijst. Daarna worden de - inhouden van HL en DE met 1 verhoogt en die van - teller BC met 1 verlaagd. - Als de inhoud van BC hierna niet nul is herhaalt - de Z80 de instructie. - - Soortgelijke commando's zijn: - - LDI: LoaD Increment - Deze instructie doet precies hetzelfde als LDIR - met het verschil dat de instructie niet herhaald - wordt. - - LDDR: LoaD Decrement Repeat - Ook hetzelfde als LDIR, maar HL en DE worden - verlaagd. Bij deze instructie staat in HL dus - bovengrens van het te verplaatsen gebied. - - LDD: LoaD Decrement - Valt te vergelijken met LDDR, maar wordt weer niet - herhaald. - - Met deze cursi hopen we je wat achtergrond - informatie te geven, maar echt leren doe je alleen door - zelf te doen ! - - Volgende keer gaan we eens wat rekenen en nog wat dinge. - - Veel programmeerplezier namens: - Ruud Gelissen en - Jan Willem van Helden - - Voor vragen zie de helplines. - (voor aanvragen bel ook gerust eens de programmeerlijn!) diff --git a/Future Disk/06/Special Effects BASIC 2.md b/Future Disk/06/Special Effects BASIC 2.md deleted file mode 100644 index ae6e0ed..0000000 --- a/Future Disk/06/Special Effects BASIC 2.md +++ /dev/null @@ -1,221 +0,0 @@ - SPECIAL EFFECTS BASIC # 2 - --------------------------- - - Welkom bij alweer de tweede aflevering van SPECIAL EFFECTS. - Ik wil het in deze aflevering gaan hebben over sprites en het - POINT commando. Op het einde zal ik ook nog twee basic scroll - routines bespreken. - - SPRITES - ------- - - Je kunt sprites in delen in twee soorten : 8 x 8 matrix - 16 x 16 matrix - - 8 x 8 - - De 8 x 8 sprites worden in 8 horizontale stukken verdeeld. - Ieder stuk is eigenlijk een binair getal. Een 1 stelt een - puntje voor , een 0 een lege plaats.Dus : - - 00011000 - 00111100 - 01111110 - 11111111 - 00011000 - 00011000 - 00011000 - 00011000 - - Je hebt nu dus een pijl.Om de Sprite in het videoram te - zetten , gebruik je : - - SPRITE$(A)=CHR$(&B00011000)+CHR$(&B00111100)+CHR$(&B01111110) - +CHR$(&B11111111)+CHR$(&B00011000)+CHR$(&B00011000)+ - CHR$(&B00011000)+CHR$(&B00011000) - - De bovenstaande pijl staat nu in het videoram. - Alleen is deze scrijfwijze nogal lang. Het handigste bij - sprites is on het HEXADECIMALE talstelsel te gebruiken. - Met het (bekende) commando PRINT HEX$(&B00000000) kun je alle - codes omzetten naar hexadecimaal. - De A bij SPRITE$(A)=-- is het SPRITENUMMER. - Dit is belangrijk bij het op het scherm zetten van een - sprite!! - - Het is wel een tijdrovende en omslachtige manier om zo - sprites te maken. Veel handiger is het als je een sprite - editor gebruikt. Zo'n sprite editor staat op deze disk onder - de naam SPRITEDT.LDR - - 16 x 16 - - De 16 x 16 sprites zijn iets moeilijker te maken dan de 8 x 8 - sprites. Je neemt hier namelijk vier 8 x 8 sprites. - Dus een 16 x 16 sprite is : - A$ C$ - B$ D$ - - A$ is de eerste 8 x 8 sprite en het kwart deel links boven - in. Als je nu net zo als bij de 8 x 8 sprites de codes in het - videoram wilt zetten (en je hebt de data in A$,B$,C$,D$) dan - doe je : - - SPRITE$(A)=A$+B$+C$+D$ - - Als je bijvoorbeeld 4 pijlen (zie 8 x 8) in 1 spritenummer - wilt hebben doe je A$= - - B$=A$ : C$=A$ : D$=A$ - SPRITE$(0)=a$+B$+C$+D$ - - In spritenummer 0 staan dus nu de 4 pijlen. - - LET OP !! JE KUNT DE SPRITES ALLEEN MAAR IN HET VIDEORAM - ZETTEN ALS JE EERST SCREEN 1 OF HOGER HEBT INGESTELD. - - SPRITE OP SCHERM - - Als je de bovenstaande pijlen in spritenummer 0 op het scherm - wilt zetten ,doe je : - - 10 screen5,2 - 20 A$= - 30 b$=a$ : c$=a$ : d$ = a$ - 40 sprite$(0)=a$+b$+c$+d$ - 50 put sprite 0,(100,100),15,0 - 60 goto 60 - - Regel 10 : de ,2 betekend dat je 16 sprites op het scherm - kunt zetten (16 sprites = 16 x 16 sprites). Er zijn ook nog - andere mogelijkheden : - ,0 : 8 sprites Normale grootte - ,1 : 8 sprites Dubbele grootte - ,2 : 16 sprites Normale grootte - ,3 : 16 sprites Dubbele grootte - - Regel 50 : PUT SPRITE A,(B,C),D,E - - A is het raster,waar de sprite op staat. Meestal is het - raster gelijk aan het spritenummer. Soms, als je bijvoorbeeld - een lopend poppetje in een sprite wilt zetten, gebruik je 1 - raster en meerdere spritenummers. - B is de X co�rdinaat, C is de Y co�rdinaat, D is de kleur en - E is het spritenummer. - - TWEE SPRITES OVER ELKAAR - - Ik kan me voorstellen dat je een sprite met 1 kleur erg saai - vindt. De mogelijkheid bestaat echter dat je twee sprites - over elkaar kunt zetten , zonder dat dit gaat knipperen of - zo. Ook kun je gebruik maken van het commando - - COLOR SPRITE$(A)= - - Als je nu bijvoorbeeld de 16 sprite pijl hebt en je wilt dat - de bovenste vier regels respectivelijk kleur 1-4 hebben en de - onderste vier regels kleur 5-8 en er tussenin kleur 9. - De color sprite$ is een RASTER !!! - - 10 screen 5,2 - 20 sprite$(0)=A$+B$+C$+D$ - 30 E$=chr$(1)+chr$(2)+chr$(3)+chr$(4)+chr$(0)+chr$(0)+ - +chr$(0)+chr$(0) - 40 F$=chr$(0)+chr$(0)+chr$(0)+chr$(0)+chr$(5)+chr$(6)+ - +chr$(7)+chr$(8) - 50 color sprite$(2)=E$+F$ - 60 putsprite 2,(100,100),9,0 - 70 goto 70 - - Dat achter color sprite$ maar twee strings komen heeft te - maken met dat je met 16 horizontale lijnen werkt. E$ geeft - dus de kleuren van de 8 bovenste regels en F$ van de 8 - onderste. - Je kunt met deze kennis bv. een lopend poppetje maken. In het - programma "WALK.BAS" zie je hoe. - - POINT - ----- - - Nu iets heel anders. De volgende keer wordt er een besproken - hoe je een spel kunt maken. Een (zeer) belangrijk commando - bij en spel is : - - A=POINT(B,C) - - In A komt te staan : de kleur van de pixel met co�rdinate B - en C. - Als je dus de kleur van pixel 100,100 wilt weten in screen 5 - doe je : - - 10 screen5 - 20 a=point(100,100) - 30 screen0 - 40 print a - - Dit commando is ook te gebruiken in een IF..THEN lus. Als je - bijvoorbeeld een sprite hebt die niet verder mag dan een lijn - van kleur 2, dan doe je : - - IF POINT(A,B)=2 then - - A en B zijn de co�rdinaten van de sprite. - - Dit is heel handig bij het maken van spelletjes. Als je een - poppetje hebt dat niet door een wit muurtje mag (kleur 15) - dan kun je dat met POINT maken : - - 10 color 15,0,0 : screen 5,2 - 20 sprite$(0)= - 30 a=250 : line (0,0)-(10,211),15,bf - 40 put sprite 0,(a,100),10,0 - 50 a=a-1 : if point (a,100)=15 then a=250 - 60 goto 40 - - In dit geval begint de sprite weer op 250,100 als de witte - balk is aangeraakt. Er zijn heel veel mogeijkheden met dit - commando en bij bijna ieder programma wordt er gebruik van - gemaakt. - - SCROLL - ------ - - En dan nu iets heel anders.Twee scroll-routines in BASIC. De - �ne met hetzelfde principe als de Machinetaal scroll , de - andere met een wat meer geschikt principe voor basic. - - SCROLL 1 - - Bij deze scroll wordt een deel van een karakter uit een strig - gecopi�rd naar page 2. In page 2 wordt de scroll opgebouwd. - Dan wordt uit page 2 de tekst gcopi�erd en dan wordt weer een - stukje karakter naar page 2 gecopi�erd. Enz,enz. (Zie voor - het copi�ren van karakter de vorige SPECIAL EFFECTS) - - Er zitten een paar nadelen aan deze scroll : - - 1 als je grote letters pakt en je copi�ert dan steeds maar 1 - lijntje dan gaat de scroll veel te langzaam. - - 2 als je meerdere lijnen copi�ert,krijg je een blokkerig - effect,als er een vertraging in staat en als je er geen - vertraging in zet, krijg je een soort knipper effect. Deze - scroll staat op deze disk onder de naam "SCROLL.BAS" - - - SCROLL 2 - - Bij deze scroll wordt de tekst alvast in de pages gezet. Als - je dan als het ware de pages "afgescant" en ieder stukje naar - page 0 copieert krijg je een goede scrol. Een voorbeeld van - zo'n soort scroll is een demootje,genaamd "DOOLHOF.BAS". De - computer gaat met een vierkantje (sprite) door het - doolhof. Het gehele doolhof staat in page 1. De computer - copieert steeds een stukje uit page 1 naar page 0. - - De volgende keer meer truuks met sprites en een eerste - spelletje. Ik hoop dat de BASIC-kennis weer iets uitgebreid - is. - - Tom Wauben - diff --git a/Future Disk/07/Machinetaal 8.md b/Future Disk/07/Machinetaal 8.md deleted file mode 100644 index 8a168f0..0000000 --- a/Future Disk/07/Machinetaal 8.md +++ /dev/null @@ -1,229 +0,0 @@ - MACHINETAALCURSUS 8 - - Het schijnt dat de lezers deze rubriek niet interessant - genoeg vinden...... - Machinetaal is wel leuk. maar niet als je alleen je - optelsommetjes ermee kunt uitvoeren. Dat kun je ook in - BASIC. Ik hoop dat jullie er echter begrip voor hebben - dat je zonder de basisbeginselen niet echt iets leuks - kunt doen. - We hopen dat je ondanks dit toch doorzet want dit is het - waard !!! Zo, en nu maar eens een beetje interessanter - proberen te doen..... - - Sprites in machinetaal. - - In navolging van de BASIC-cursus volgt hier de besturing - van sprites in machinetaal - (p.s. Tom, dit gaat echt veel sneller in machinetaal). - - Het definieren van een Sprite patroon (de vorm) is - vrijwel gelijk aan de methode die in basic wordt - gebruikt. Persoonlijk gebruiken we liever de T&E-soft - sprite-editor SPEN, omdat je m.b.v het "MAKE2" commando, - eenvoudig meerkleurige sprites in data kunt omzetten die - je gewoon in je programma kunt gebruiken. - - HET SPRITEPATROON - - Hier volgt een voorbeeld van een 8*8 sprite - - SPRPAT:db %01100110 - db %01100110 - db %01100110 - db %01111110 - db %01100110 - db %01100110 - db %01100110 - db %01100110 - - Een spritepatroon definier je regel voor regel. - Elke regel stel een lijn van je sprite voor. - Een ��n (staat hier 1 Kubie?) stel een puntje voor, een - nul is een doorzichtbare plaats in je sprite. - - Met de onderstaande routine kun je de spritemode op 8*8 - zetten: - - WRTVDP:EQU #47 ; SCHRIJF VDPREGISTER - - LD A,(#F3E0) ; VDP REGISTER 1 - AND 253 ; RESET BIT 1 - LD B,A - LD C,1 - CALL #48 - - Alles wat sprites betreft staat in het VRAM (videoram). - Je kunt de Spritepatronen in het VRAM zetten m.b.v. - onderstaande routine: - - LDIRVM:EQU #5C ; LDIR NAAR VRAM - - LD HL,SPRPAT - LD DE,#7800 - LD BC,8*8 - CALL LDIRVM - RET - - SPRPAT:db %01100110 - db %01100110 - db %01100110 - db %01111110 - db %01100110 - db %01100110 - db %01100110 - db %01100110 - - 64 bytes (in registerpaar BC) worden door Ldir VRAM in - het Videogeheugen gezet op adres #7800. - Hier begint standaart de Spritepatroontabel. - Deze tabel loopt tot #7FFF, dit houdt in dat je maximaal - 256 8*8 sprites kunt definieren of 64 16*16 sprites. - Zodra deze routine uitgevoerd is staat in het VRAM je - spritepatroon. - - DE SPRITECOLOR - - Je kunt een sprite per horizontale lijn een kleur geven. - Alle "eenjes" in je patroon krijgen nu deze kleur. - M.b.v. de volgende routine kun je dit bewerkstelligen: - - WRTVDP:EQU #47 ; SCHRIJF VDPREGISTER - LDIRVM:EQU #5C ; LDIR NAAR VRAM - LD HL,SPRCOL - LD DE,#7400 - LD BC,16 - CALL LDIRVM - - - Naar het VRAM op adres #7400 worden nu de spritekleuren - geschreven. Je moet er rekening mee houden dat de - kleuren van de 2de sprite pas op adres #7410 moeten - komen te staan (dat is 16 verder !! en heeft te maken - met 16*16 sprites waarbij je 16 bytes voor de kleuren - nodig hebt.). - De kleurnummers stemmen overeen met de paletkleuren, je - krijgt dus nu een half rode, half blauwe sprite. - - Zo, kleuren en patronen staan in het Vram, nu onze - sprite nog besturen. - - LDIRVM:EQU #5C ; LDIR NAAR VRAM - - LD HL,SPRATT ; ATTRIBUTEN - LD DE,#7600 - LD BC,4 - CALL LDIRVM - RET - - SPRATT:DB 100,128,0,0 - - Na het uitvoeren van dit programmatje zien we een sprite - verschijnen op het beeldscherm. - De y-coordinaat is 100 - De x-coordinaat is 128 - In de 3de byte staat het spritenummer, in dit geval 0, - dat houdt in dat het eerste spritepatroon op het - beeldscherm verschijnt. Om de 2de sprite te zien te - krijgen moet je hier een 1 neerzetten. - Let goed op, je krijgt nu alleen het 2de spritepatroon - te zien en niet de 2de spritecolors. - De spritecolors zijn namelijk verbonden aan de - attribuuttabel. Bij de eerste 4 bytes in de - spriteattribuuttabel horen dus de eerste 8 (eigenlijk - 16) bytes in de spritecolortabel.Bij de tweede 4 bytes - in de spriteattribuuttabel horen dus de tweede 16 bytes - in de spritecolortabel enz. (#7400+16) - - Nu volgt dan een uitgebreider voorbeeld van de besturing - van 2 sprites. - - WRTVDP:EQU #47 ; SCHRIJF VDPREGISTER - LDIRVM:EQU #5C ; LDIR NAAR VRAM - DB #FE - DW ST,EN,ST - - ORG #A000 - ST: LD A,(#F3E0) ; VDP REGISTER 1 - AND 253 ; RESET BIT 1 - LD B,A - LD C,1 - CALL #48 ; SPRITES 8*8 - LD HL,SPRPAT ; PATRONEN IN VRAM - LD DE,#7800 - LD BC,8*8*2 - CALL LDIRVM - LD HL,SPRCOL ; COLORS IN VRAM - LD DE,#7400 - LD BC,16*2 - CALL LDIRVM - LOOP: - XOR A ; SPATIE ? - CALL #D8 - RET NZ ; JA, STOP - LD HL,(TABPNT) ; HAAL YCO. UIT TABEL - LD A,(HL) - LD B,A ; BEWAAR TABELWAARDE - INC A - CALL Z,REPEAT ; 255 ? JA, HERHAAL - INC HL ; VOLGENDE YCO. - LD (TABPNT),HL - LD (SPRATT),A ; ZET YCO. SPRITE 1 GOED - LD A,(SPRATT+1) - ADD A,4 - LD (SPRATT+1),A ; VERHOOG XCO. SPRITE 1 - LD (SPRATT+4),A ; ZET YCO. SPRITE 2 - LD A,B ; ZET XCO. SPRITE 2 - LD (SPRATT+5),A - EI - HALT ; WACHT OP INTERUPT - LD HL,SPRATT ; ATTRIBUTEN - LD DE,#7600 - LD BC,4*2 - CALL LDIRVM - JP LOOP - - REPEAT:LD HL,TABEL ; START TABEL - LD A,(HL) - LD B,A - RET - - TABPNT:DW TABEL - TABEL: DB 10,11,13,15,18,21,26,31,37,43 - DB 43,37,31,26,21,18,15,13,11,10,255 - SPRATT:DB 0,0,0,0 - DB 16,50,1,0 ; SPRITE NUMMER 1 - - SPRCOL:DB 15,15,15,15,15,15,15,15 - DB 00,00,00,00,00,00,00,00 ; DUMMIES - DB 15,15,15,15,15,15,15,15 - DB 00,00,00,00,00,00,00,00 ; WORDT NIET HEEN - ; GEKEKEN - SPRPAT:db %11001100 - db %00100100 - db %01111110 - db %01101011 - db %11111111 - db %11011101 - db %01100011 - db %00111110 ; EINDE EERSTE SPRITE - - db %01100110 ; 2DE SPRITE - db %01100110 - db %01100110 - db %01111110 - db %01100110 - db %01100110 - db %01100110 - db %01100110 - - EN: END - - Voer dit maar eens uit en als het goed is zul je 2 - sprites zien bewegen. Je kunt natuurlijk b.v. een - sinustabel in basic in het geheugen "poken" enz. - - Tot zover deze keer, voor special requests wendt je tot - Ray Cokes of Ruud Gelissen. - Ajuu J.W. en Ruud. Aleih gank maar es get angers leze, - manne.(Vert.: Wilt U alstublieft een andere tekst gaan lezen) diff --git a/Future Disk/07/Special Effects BASIC 3.md b/Future Disk/07/Special Effects BASIC 3.md deleted file mode 100644 index d5ea0e1..0000000 --- a/Future Disk/07/Special Effects BASIC 3.md +++ /dev/null @@ -1,218 +0,0 @@ - SPECIAL EFFECTS BASIC # 3 - +++++++++++++++++++++++++ - - Alweer de derde aflevering van SEB. Deze keer leert U een - uitgebreid tekenprogramma te maken. De besturing, pages enz - worden besproken . Maar eerst het tweede deel van SPRITES. - - - SPRITES #2 - ---------- - - Zoals de vorige keer bescheven zijn sprites (ltrl. GEESTEN) - handig voor gebruik in eigen programma's. Om een sprite in 't - geheugen te zetten, is er in BASIC het commando SPRITE$(A)=- - (zie vorige cursus). Er is ook een andere manier: - De data wordt in een DATA file meteen in het sprite geheugen - ingelezen. Om dit te begrijpen eerst nog een stukje theorie - over het V-ram. - In het V-ram heeft iedere screen zijn eigen geheugen. Zo is er - er geheugen voor karakters, kleuren etc. Ook voor sprites is - er in iedere screen een stukje gereserveerd. Een klein - overzichtje zal dit duidelijk maken : - - KARAKTER POSITIE TABEL (geeft de karakterposities op beeld - weer) - KARAKTERVORM TABEL (vorm van de karakters) - - KLEUREN TABEL (bepaalt kleur die elke beeldpositie heeft) - - PALET TABEL (bevat alle R-G-B tinten van iedere kleur) - - SPRITE KLEUREN TABEL (bevat de kleuren van COLOR SPRITE) - - SPRITE ATTRIBUTE TABEL (bevat info. over sprite: grootte , - positie enz.) - SPRITE VORM TABEL (bevat vorm van sprites) - - Sommige screens hebben ��n tabel niet (bv. screen 0 heeft - geen SPRITE vorm tabel). Iedere tabel gebruikt een stukje - V-ram. Het is mogelijk hierin te schijven. We kunnen dus een - sprite meteen in het geheugen poken. - Het poken in het V-ram gaat met het bevel: - - VPOKE A,B : in A staat het V-ram adres en in B de waarde. - - Om nu in het V-ram een sprite te zetten, moet je dus het - adres weten van de SPRITE-VORM TABEL in de gewenste screen. - Een sprite die je aan het begin van de tabel poked heeft - spritenummer 0, de tweede nr. 1 enz. - Het volgende programmaatje zet een sprite die de DATA in de - DATA-regels heeft staan in het V-ram (screen 5) - - 10 SCREEN 5,0 : 'een 8 sprite - 20 FOR I=0 TO 7 : '8 DATA'S - 30 READ A : 'LEES WAARDE IN A - 40 VPOKE &H7800+I,A:'HET EERSTE ADRES VAN DE SPRITE-VORM TABEL - IS &H7800. DE SPRITE KOMT DUS HELEMAAL IN HET BEGIN TE STAAN - 50 NEXT I - 60 'OPROEPEN SPRITE (=NORMAAL) - 70 PUT SPRITE 0,(128,106),15,0 - 80 GOTO 80 - 90 'DATA REGEL SPRITE (GESTREEPT VLAKJE) - 100 DATA 255,0,255,0,255,0,255,0 - - Deze manier is vooral handig bij veel sprites. Schrijf alle - data in het gewone RAM, save het weg en laad dit in het V- - ram op de juiste plaats. Dit komt nog in een volgende cursus - bod. - - Dit zelfde vehaaltje geldt voor COLOR SPRITE. - - Genoeg over sprites. We gaan nu een tekenprogrammaatje maken. - - SEB-GRAPH - --------- - - Om een eigen programma te maken zullen we eerst de besturing - d.m.v. de randapparatuur (toetsenbord,joystick enz.) - bespreken. De besturing van toetsenbord en joystick is het- - zelfde. Er zijn nl. 8 richtingen en een rust plaats. In een - schema ziet dat er zo uit : - 1 - 8 2 - 7 0 3 - 6 4 - 5 - - Richting 5 is bv. dat er naar onder is gedrukt op het toetsen - bord of joystick. - Zoals in het bovenstaande schema geeft de computer de - richtingen weer m.b.v. het commando : - - A = STICK(B) : A komt de waarde te staan (0-8 , zie - bovenstaande schema) en in B staat de poort - waarvan moet worden gelezen in B kan staan: - 0 : Toetsenbord - 1 : Joystick poort 1 - 2 : Joystick poort 2 - Let op! A is altijd een variable , B is - een constante. - - M.b.v. deze kennis kun je bv. een menuutje maken in screen 0. - Kijk maar in de onderstaande listing ; - - 10 SCREEN 0 : WIDTH 80 : KEY OFF :'INSTELLINGEN - 20 CLS : FOR I = 1 TO 5 : READ A$ : LOCATE 30,I:PRINT A$ - 'Zie onderstaande informatie - 30 NEXT I - 40 IF STRIG(0) OR STRIG (1) OR STRIG (3) THEN 110 - 50 A=STICK(0):IF A=0 THEN A=STICK(1) : IF A=0 THEN - A = STICK (2) : IFA=0 THEN GOTO 40 - 60 IF A=1 THEN Y=Y-1 : IF Y<1 THEN Y=5 - 70 IF A=5 THEN Y=Y+1 : IF Y>5 THEN Y=1 - 80 LOCATE 28,YO : PRINT " " : LOCATE 39,YO : PRINT " " - 90 LOCATE 28,Y : PRINT ">" : LOCATE 39,Y :PRINT "<" - 100 YO=Y : GOTO40 - 110 IF Y = 5 THEN END ELSE RESTORE 130 : FOR I=1 TO Y : - READ A$ : NEXT I - 120 RUN A$+"LDR" - 130 DATA MENU - 140 DATA MAGAZINE - 150 DATA DEMO - 160 DATA AUTOEXEC - 170 DATA STOP - - Een eerste langere listing. Nog even wat uitleg : - - Regel 20 : READ A$ : in a$ komt de data te staan die achter - commando DATA staat. Wordt er nog een READ A$ - gedaan dan springt de computer automatisch naar de - sting achter de komma of de string achter een - nieuwe DATA-regel (in dit geval). - RESTORE in regel 110 geeft aan waar de DATA moet - worden gelezen.(in dit geval regel 130) - - Regel 40 : hier staat een nieuw commando : - - IF STRIG (A) THEN : Dit commando gaat naar regel als - er een knop/spatie van toetesenbord , - joystick of muis wordt ingedrukt. - In A staat : - - 0 spatiebalk - 1 joystick / muis poort 1 , knop 1 - 2 joystick / muis poort 1 , knop 2 - 3 joystick / muis poort 2 , knop 1 - 4 joystick / muis poort 2 , knop 2 - - In dit geval wordt er naar regel 110 gesprongen als er spatie - of knop 1 van joyst./muis in poort 1 of 2 wordt gedrukt. - - (Dit programmaatje staat op deze disk onder de naam - "SEBMENU.LDR") - - het lezen van de besturing van de muis - -------------------------------------- - Om de muis te lezen is er ook een appart commando : - - PAD (A) : A kan 18 waardes hebben. Hier worden alleen de - waardes voor de muis in poort 1/2 besproken. - - MUIS in poort 1 : eerst de altijd PAD (12) doen. Dit is om - een de MUIS-DATA te "openen". PAD (13) - geeft de X vershuiving en PAD (14) de - Y vescuiving. - MUIS in poort 2 : hetzelfde verhaal alleen met resp. PAD (16) - PAD (17) en PAD (18) - - In het programma CUJOMU.LDR kunt u alle besproken besturings- - vormen in een programma zien. U kunt dit programma ook voor - eigen gebruik gebruiken. Dit programmaatje vormt de basis - voor het tekenprogrammaatje. - - Om te kiezen tussen de verschillende opties (lijn tekenen - enz.) maken we bebruik van IKONEN. Deze tekeningetjes worden - ingeladen in PAGE 1. (zie SEB #1). In page 2 wordt de oude - tekening bewaard. - - Het enige commando wat we nu nog niet kennen om het - tekenprogramma af te maken is : - - ON A GOSUB , , : dit commando spring naar de sub - routine die begint op regel B - als A 1 is , sprint naar regel als A 2 is enz. - - Een voorbeeldje : - - 10 D=STICK (0) : IF D=0 THEN10 - 20 ON D GOSUB 40,50,60,70,80,90,100,110 - 30 GOTO 10 - 40 PRINT "BOVEN" : RETURN - 50 PRINT "RECHTS-BOVEN" : RETURN - 60 PRINT "RECHTS" : RETURN - 70 PRINT "RECHTS-ONDER" : RETURN - 80 PRINT "ONDER" : RETURN - 90 PRINT "LINKS-ONDER" : RETURN - 100 PRINT "LINKS" : RETURN - 110 PRINT "LINKS-BOVEN" : RETURN - - Deze listing gaat dus naar regel 40 als D=1(boven). - - Nu kunnen we dus SEB-GRAPH maken. Op deze disk staat het - tekenprogrammaatje onder de naam SEB-GRPH. Bekijk gerust de - list eens. Daar leert U veel van. - - Tot slot nog een denkspelletje waarin veel van het - bovenstaande wordt gebruikt. Start het maar eens op (DENKSPEL - .LDR) en speel. Als het goed is kunt U zoiets nu ook maken. - - - Veel theorie deze keer, maar U ziet : je kunt er leuke - dingen mee maken. Volgende keer proberen we eens een echt - spelletje te maken. Is bij U al de programmeer drift - toegeslagen , stuur dan eens een eigengemaakt programmaatje - op naar het bekende FUTURE-DISK adres (zie helplines). - Heb je nog vragen , bel dan 046-758100 (na 16.00 U. Tom). - - Tom Wauben diff --git a/Future Disk/075/Machinetaal Cursus 9.md b/Future Disk/075/Machinetaal Cursus 9.md deleted file mode 100644 index 8c1e816..0000000 --- a/Future Disk/075/Machinetaal Cursus 9.md +++ /dev/null @@ -1,204 +0,0 @@ -MACHINETAAL CURSUS DEEL 9 -------------------------------- - -Na de vorige keer mooi de BASIC cursus gevolgd te hebben, -gaan we nu mooi zelf aan de slag met oersaaie, maar broodno- -dige, mcode. -Deze keer behandelen we de MSX2 SUB-ROM en de schuif- en ro- -teerfuncties. - - SCHUIF- EN ROTEERFUNCTIES -------------------------------- -De schuif- en roteerfuncties zijn bedoeld om binnen een -register de bits te verschuiven. -Schuifinstructies schuiven alle bits 1 naar rechts of 1 naar -links, roteerfuncties doen dit ook, maar roteren de inhoud -van de laagste bit in de hoogste, of andersom. -We bespreken d'er een rits (allemaal dus !!): - -* RLCA (Rotate Left Circular Accumulator) - -Roteert de inhoud van register A 1 bit naar links. De inhoud -van bit 7 komt in de Carry vlag en in bit 0. -Je kunt dus snel de inhoud van de hoogste bit van A testen -met deze instructie en dan op de carry te testen. - -* RLA (Rotate Left Accumulator) - -Doet bijna hetzelfde als een RLCA, maar de inhoud van de -Carry bit komt nu in bit 0. - -* RRCA (Rotate Right Circular Accumulator) - -Zie RLCA, maar i.p.v. naar links te schuiven schuift deze -instructie naar rechts en komt bit 0 nu in de Carry en in bit -7. - -* RRA (Rotate Right Accumulator) - -Zie RLA, maar i.p.v. naar links te schuiven schuift deze -instructie naar rechts en de inhoud van bit 0 komt in de -Carry. De Carry gaat naar bit 7. - -Tot zover de instructies die alleen op register A betrekking -hebben. Nu de rest van de instructies die je op alle 8 bits -registers te gebruiken zijn. - -* RLC r (Rotate Left Circular) - -Deze instructie doet hetzelfde als de instructie RLCA. Nu kun -je dus in alle 8 bits registers schuiven. -Ook kun je deze instructie gebruiken in de volgende formaten: -RLC (IX+d) -RLC (IY+d) -RLC (HL) -Nu schuif je dus met de inhoud van geheugenlocaties waarheen -dat 16 bits register verwijst. - -* RRC r (Rotate Right Circular) - -Deze instructie doet hetzelfde als de instructie RRCA. -Ook deze instructie werkt weer zo: -RRC (IX+d) -RRC (IY+d) -RRC (HL) - -* RL m (Rotate Left) - -Deze instructie doet hetzelfde als RLA. Werkt op alle 8 bits -registers. - -* RR m (Rotate Right) - -Deze instructie doet hetzelfde als RRA. Werkt op alle 8 bits -registers. - - -* SLA m (Shift Left Arithmetic) - -Dit is de eerste schuifinstructie. -Alle bits worden 1 plaats naar links geschoven, waarbij bit 7 -in de Carry wordt geschoven en in bit 0 komt een 0. - -* SRA m (Shift Right Arithmetic) - -Alle bits gaan 1 naar rechts. Bit 0 komt in de Carry en de -inhoud van bit 7 verandert niet. - -* SRL m (Shift Right Logical) - -Hetzelfde als SRA, maar in bit 7 komt een 0. - -* RLD (Rotate Left Digit) - -Dit is een verplaatsing van nibbles (groupies van 4 bits) -tussen register A en de inhoud van HL, (HL). De onderste -nibble van A (bit 0-3) komt in de onderste nibble van (HL). -De onderste nibble van (HL) komt in de bovenste. De bovenste -nibble van (HL) komt in de onderste nibble van A (jaja). -* RRD (Rotate Right Digit) - -Ook dit is een verplaatsing van nibbles tussen A en (HL). -De onderste nibble van A gaat naar de bovenste van (HL). -De bovenste van (HL) gaat naar de onderste van (HL). -En de onderste van (HL) gaat naar de onderste van A -(jajajaja). - -Omdat al deze instructies moeilijk te begrijpen zijn zonder -begleidende schema's, staat er op deze disk een .PTC file. -Deze kun je in Dynamic Publisher inladen. -Tenminste ......... als het oppermonster 'm niet gewist of -gecrunched heeft (RED. det is toch waardeloze zeik !!). - - HET SUB ROM - ------------- - -Aarg, er zit nog meer ROM in je MSX 2!!! Je dacht dat je met -de BIOS plus BASIC alles had, kom je bedrogen uit. De schele -makers van de MSX 2 vonden dat ze te weinig plaats hadden -voor typische MSX 2 routines. Daarom werd er nog een 16K -groot ROM gemaakt dat ergens in 1 van de slots geplaatst -werd. Omdat het slot systeem nogal moeilijk is, hebben de -programmeurs van ASCII op adres #15F een BIOS routine gemaakt -waarmee je makkelijk het Subrom kunt aansturen. -Deze routine werkt als volgt: -In register IX plaats je het adres van de Subrom routine, die -je wilt gebruiken. Een paar voorbeelden: - -GRTPRT: EQU #89 -LD A,5 -CALL #5F -LD A,"A" -LD IX,GRTPRT -CALL #15F -RET - -Deze routine print een teken op de grafische schermen 5 tot 8 -en verwacht dit teken in register A. Vergelijk in BASIC de -instructie: OPEN "GRP:" AS#1: PRINT #1,"A". - -SETPLT: EQU #14D -LD A,5 -CALL #5F -LD D,15 -LD A,%11110000 -LD E,0 -LD IX,SETPLT -CALL #15F -RET - -Deze routine verandert een kleur van je palet. In A moet je -in de bovenste nibble de roodintensiteit zetten en in de -laagste nibble de blauwintensiteit. In E zet je in de laagste -nibble de groenintensiteit. In D staat het te veranderen -colornummer. In BASIC is dit: COLOR=(15,7,0,0). - -De routine NEWPAD op #1AD kan de muis aansturen. Dit werkt -ongeveer hetzelfde als in basic. Als je de BASIC begrijpt kun -je het onderstaande machinetaalprogrammaatje ook wel -ontcijferen. - -NEWPAD: EQU #1AD -LD A,12 -LD IX,NEWPAD ;Schakel muis aan. -CALL #15F -LD A,13 ;Lees X-offset uit -LD IX,NEWPAD ;(optellen bij oude X-co.) -CALL #15F -PUSH AF ;bewaar X-offset -LD A,14 ;Lees Y-offset uit -LD IX,NEWPAD ;(optellen bij oude Y-co.) -CALL #15F -LD B,A ;Y-offset in B. -POP AF - -Voor een geheel overzicht van het Subrom kun je contact -opnemen met de programmeerlijn. - -Eigenlijk hadden we nog een mooie grote listing willen laten -zien, waarin veelvuldig gebruikt wordt gemaakt van de schuif- -en roteer instructies. Maar des te langer je er over gaat -nadenken, des te moeilijker wordt het om iets zinnings te -verzinnen. Toch nog een klein voorbeeldje: - -LD A,#F0 ;HOOGSTE NIBBLE VOL -RRCA ;IN A: %01111000 -RRCA ;IN A: %00111100 -RRCA ;IN A: %00011110 -RRCA ;IN A: %00001111 -AND %00001111 ;BOVENSTE NIBBLE WISSEN - -Soms moet je gaan rekenen met de bovenste nibble. Nu is dat -flink lastig. Daarom is het handig om de bovenste nibble in -de onderste te schuiven. De AND op het einde is eigenlijk -niet nodig, maar als er al data in de onderste nibble staat, -wordt deze doorgeschoven in de bovenste bits. - -Door een foutje werkte het programma SPRITES vorige keer -niet. Dit is verholpen en dan hopen dat in de rebount alles -goed gaat. - -Veel programmeer plezier en een prettige vakantie, - - Ruud Gelissen, - Jan Willem van Helden diff --git a/Future Disk/075/Special Effects BASIC 4.md b/Future Disk/075/Special Effects BASIC 4.md deleted file mode 100644 index 3797b5c..0000000 --- a/Future Disk/075/Special Effects BASIC 4.md +++ /dev/null @@ -1,593 +0,0 @@ -Speciale dank gaat uit naar J.B.Vonk. - - - - SPECIAL EFFECTS BASIC #4 - ------------------------ - - Welkom bij het vierde deel van Special Effects. Deze keer - (nog) een deel van sprites, de logische operaties , de uitleg - van PAC-IT , een pacman-kloon en tot slot nog het DEF FN , - ON INTERVAL en INSTR commando , een aantal losse flodders die - handig zijn bij het programmeren in BASIC .... - - - - SPRITES (4) - +-+-+-+-+-+ - - Deze keer een korte SPRITES-cursus. De volgende (en tevens - laatste) SPRITES zal een aantal truuks laten zien met - sprites. - Deze keer wordt alleen de 3 kleurige sprite uit de doeken - gedaan en nog een paar aardigheidjes met het color sprite$ - commando. - - Jazeker. Ook driekleurige sprites zijn mogelijk terwijl er - maar 2 sprites over elkaar worden gezet. Waar de 2 sprites - elkaar overlappen, worden deze ge-ORd (zie LOGISCHE OPERATIES - , hieronder). Zo kan deze 3e kleur worden berekend. U kunt - dan zelf de gewenste kleur geven met COLOR=. (zie SEB #1). - - Maar hoe wordt dit dan gedaan ?? - - De zesde bit van de colorsprite$-byte wordt geset. - Deze byte ziet er als volgt uit - - | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | - --------------------------------- - |VPb|ORb|IGb|nvt|CLR|CLR|CLR|CLR| - - - VPb (bit 7) : als deze bit geset is , wordt de sprite 32 - pixels naar links verplaatst. - - ORb (bit 6) : als deze bit geset is en twee sprites - overlappen, zal er een OR-operatie tussen deze twee kleuren - plaatsvinden en deze kleur wordt op het scherm afgebeeld. - - IGb (bit 5) : de sprite-overlapping wordt genegeerd. - - Bit 4 heeft geen functie. - - CLR (bit 0 t/m bit 3) : deze bits geven de spritekleur aan. - - - Als bijvoorbeeld de spritelijn-kleur van sprite I 12 moet - zijn en van sprite II 10 en ze moeten ge-ORd worden, dan - moet bit 6 geset zijn : - - SPRITE I : &b01001100 'bit 6 geset en kleur 12 (&b1100) - - SPRITE II : &b01001010 'bit 6 geset en kleur 10 (&h1010) - - In een list : - - 10 COLOR 15,0,0 : SCREEN 5,0 - 20 A$=CHR$(&HFF)+CHR$(&HFF)+CHR$(&HFF)+CHR$(&HFF) - 30 SPRITE$(0)=A$+A$ - 40 SPRITE$(1)=A$+A$ - 50 COLOR SPRITE$(0)=CHR$(&B01001100) - 60 COLOR SPRITE$(1)=CHR$(&B01001010) - 70 PUT SPRITE 0,(100,100),,0 - 80 PUT SPRITE 1,(104,100),,1 - 90 GOTO 90 - - De sprites worden ten opzichte van elkaar 4 pixels - verschoven. Ze overlappen elkaar dus van (104,100)-(108,100) - Daar wordt de kleur dus : - - 1100 - 1010 or - ------- - 1110 'color 14 !!! - - - LET OP !! Voor iedere sprite-lijn is een colorsprite$-bit, - dus kunt u in totaal maar liefst 32 kleuren in 2 sprites - gebruiken. - - Het aardige programmaatje SPRITES.BAS laat alle besproken - mogelijkheden nog eens zien. - - - - LOGISCHE OPERATIES - +-+-+-+-+-+-+-+-+- - - Een logische operatie is een bewerking van een - variable ,copy,enz. - - VARIABLE - -------- - - De "hoofd" logische operaties zijn de AND,OR,XOR. - - AND X Y XY OR X Y XY XOR X Y XY - - 0 0 0 0 0 0 0 0 0 - 1 0 0 1 0 1 1 0 1 - 0 1 0 0 1 1 0 1 1 - 1 1 1 1 1 1 1 1 0 - - U ziet het is dus eigenlijk een bewerking van BITs. Maar als - u nu bv. een in A staande waarde wilt ANDen dan typt U - - PRINT A AND 0 - 0 - - Er komt nu altijd nul uit , want als U met 0 AND dan komt er - altijd 0 uit (alleen als X en Y 1 zijn dan komt er 1 uit.) - - Nu zijn hier hele leuke dingen mee te doen , in BASIC zouden - er nog wel andere commando's nodig kunnen zijn bv. als X=0 en - Y=0 dan XY=1 . Daarom volgt hieronder nog een lijst(je) met - aanvullende (afgeleid van AND,OR en XOR) logische operaties. - - NOT X Y XY EQV X Y XY IMP X Y XY - - 0 - 1 0 0 1 0 0 1 - 1 - 0 1 0 0 1 0 0 - - - 0 1 0 0 1 1 - - - 1 1 1 1 1 1 - - De NOT functie is handig bij het kijken of een variable 0 is. - Van deze logische operatie kan het resultaat bekeken worden - met : - - PRINT NOT A - - De EQV is de omgekeerde XOR functie (EQV = Exclusive Or - Negative , XOR = eXlisive OR) , zoals de naam het al zegt. - - En dan het IMP commando. Zelf heb ik het nog nooit gebruikt - en ik denk dat deze logische operatie dan ook volstrekt - zinloos is. - - COPY,LINE - --------- - - Er zijn ook logische operaties m.b.t. het copie�ren en het - tekenen van een lijn. In SEB #1 is de operatie TPSET aan bod - gekomen. Hieronder volgt een lijst van alle logische - operaties bij een COPY : - - AND : Voert een AND operatie op de kleuren uit (zie VARIABLE) - - OR : Voert een OR operatie op de kleuren uit (zie VARIABLE) - - XOR : Voert een XOR operatie op de kleuren uit (zie VARIABLE) - - PRESET : Voert een INVERSE (NOT) uit op de kleuren. Iedere - bit die geset is (1) wordt 0 en iedere bit die 0 is - wordt 1. - - PSET : De normale copy. - - Ook bestaan de bovenstaande commando's met een T ervoor - (TAND,TOR,TXOR,TPRESET,TPSET). Dit betekend dat color 0 als - doorzichtig wordt beschouwd (en dat de achtergrond dus te - zien is). - - Een voorbeeldje : - - 10 COLOR 0,0 : SCREEN 5 : CIRCLE (25,25),25,10 - 20 LINE (100,100)-(200,200),2,BF : GOTO 140 - 30 COPY(0,0)-(50,50) TO (125,125),0,AND : RETURN - 40 COPY(0,0)-(50,50) TO (125,125),0,TAND : RETURN - 50 COPY(0,0)-(50,50) TO (125,125),0,XOR : RETURN - 60 COPY(0,0)-(50,50) TO (125,125),0,TXOR : RETURN - 70 COPY(0,0)-(50,50) TO (125,125),0,OR : RETURN - 80 COPY(0,0)-(50,50) TO (125,125),0,TOR : RETURN - 90 COPY(0,0)-(50,50) TO (125,125),0,PRESET : RETURN - 100 COPY(0,0)-(50,50) TO (125,125),0,TPRESET : RETURN - 110 COPY(0,0)-(50,50) TO (125,125),0,PSET : RETURN - 120 COPY(0,0)-(50,50) TO (125,125),0,TPSET : RETURN - 130 'HOOFDLUS , SPRING IEDERE KEER NAAR ANDERE COPY. - 140 D=D+1 : A$=INPUT$(1) - 150 ON D GOSUB 30,40,50,60,70,80,100,110,120 - 160 GOTO 160 - - Met dit programma kunt u alle verschillende logische - operaties zien. Bekijk bij iedere operatie de kleuren maar - eens. Dit is een zeer beknopt programma. In de file - "COPYLOG.BAS" kunt U een uitgebreider programma zien. - - U kunt deze logische operaties ook gebruiken bij het LINE - commando. Zie daarvoor "LINELOG.BAS". Kijk ook gerust eens in - de LIST. U kunt hier veel van leren. - - Genoeg over de logische operaties. U zult ook in andere - programma's deze logische operaties zien en zelfs in ML wordt - een deel ervan gebruikt. Dit komt doordat de logische - operaties erg snel zijn. Experimenteer gerust , Uw computer - heeft eindeloos gedult. - - - Deze tekst is een beetje lang , zodat hij in 2 delen - gesplitst moest worden. - - Lees verder bij het 2e deel ..... - - Special Effects Basic #4 (vervolg) - ---------------------------------- - - - - PAC-IT - ++++++ - - Al een paar keer werd het aangekondigd , maar nu beginnen we - dan toch echt met een spel , PAC-IT. Het is een kloon van het - overbekende spel PACMAN. Toch is zo'n simpel uitziend spel - nog ingewikkeld. In dit deel gaan we niet verder dan de - opbouw van het speelscherm en een deel van de hoofdlus - (lopen, happen en stoppen voor een muur.) - In de volgende SEBs komt de rest van het spel aan bod. - Maar voordat u begint te lezen zou het handig zijn de - listing bij de hand te hebben. Druk dan nu op reset , laad - de file PACIT.BAS,zet de printer aan , druk op de J , laad - daarna de file MAGAZINE.LDR en lees verder ... - - VRAAG 1 - +++++++ - - De eerste vraag is het probleem van "welke screen ?". De - screenmode wordt bij dit spel screen 5. - In deze screen kan er namelijk van een groot aantal - commando's gebruik worden gemaakt zoals SET PAGE,POINT, - COPY enz. - - Om bij het begin te beginnen , gaan we eerst eens aan de - grafische aspecten werken. Hieronder wordt verstaan : de - sprites,de achergrond,de scorelijst enz. Dit is dan ook het - begin van de listing. Meteen daarna komt de hoofdlus. Dat is - in dit geval de besturing en het happen. - - DE GRAPHICS - +++++++++++ - - De sprite(s) van PACCIE is getekend met de SPRITE-EDITOR van - futuredisk #6. Deze worden met het programaatje SPRITE.LDR - (ook van FD #6) in het V-ram ingeladen. - De scorelijst-met-cijfers- tekening is getekend in (volgens - mij) het beste screen 5-tekenprogramma : DD-graph. - Deze tekening (PACIT.DAT) is , zoals de extensie zegt , een - DAT-file (inladen m.b.v. COPY "" TO (A,B),PG). - De co�rdinaten zijn zelf opgemeten en daarmee wordt alles op - de goede plaats gezet. - - DE BESTURING - ++++++++++++ - - De besturing van PAC-IT is iets anders dan de besturing van - CUJOMU (die er niet op FUTUREDISK 7 stond, maar nu wel van - de partij is). PACCIE moet nl. altijd doorlopen (totdat hij - tegen een muur loopt). Daarom staan in variablen X en Y - respectivelijk de X en de Y STAP (!). De co�rdinaten van de - sprite zijn de variablen A en B. Deze worden dus iedere keer - met X resp. Y opgeteld. Deze X en Y stap worden weer bepaald - door de variable K. Hierin staat hoe groot de X en Y stap - moet zijn. Als u K dus verandert, zal de stap ook - veranderen. - - Ook het spritenummer wordt bij iedere verandering van - richting gegeven. Dit zou ook via een ingewikkelde formule - kunnen, maar dit is makelijker. - - MUUR ??? - ++++++++ - - POINT .. Het is al eerder gezegd, maar het POINT-commando - komt toch altijd weer aan bod. Ook bij PAC-IT neemt het een - grote plaats in nl. bij het "zien" van een muur. Er moet dan - gestopt worden. Haalt u de POINT-regels maar eens uit het - programma en alles zal in de soep lopen. - - Bij iedere beweging van de sprite wordt er gekeken of er nog - niet tegen een muur aangebotst is. Op alle 4 de hoeken van - de sprite (A,B/A+8,B/A,B+8/A+8,B+8) wordt gekeken of er geen - puntje (POINT !!) van kleur 12 zit (de kleur van de muur). - Is dit wel het geval , dan wordt de A en B met de X en de Y - stap afgetrokken, met als gevolg dat de sprite stil blijft - staan. - - HAPPEN - ++++++ - - Ook bij het HAPPEN van de witte blokjes, speelt het POINT- - commando de hoofdrol. Er wordt nl. iedere keer gekeken of - de sprite op kleur 15 staat (de kleur van de blokjes). Zo - ja, dan wordt er een zwart blokje overheen gezet, zodat het - lijkt alsof PACCIE het blokje heeft opgegeten. - - De volgende keer krijgt PACCIE zijn tegenstanders te zien. - - - - DEF FN , ON INTERVAL en INSTR - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Tot slot nog enkele handige BASIC commando's. - - DEF FNA (X,Y)= Met dit commando kunt U een - eigen vergelijking laten oplossen - Het bijbehorende commando waarmee U de vergelijking kunt - laten werken is - - A=FNA In A komt dan de uitgerekende waarden. Bv. - - 10 'Voorbeeld DEF FNA - 20 ' - 30 DEF FNA (X,Y) =(X*X)+Y - 40 FOR X=0 TO 4 - 50 A=FNA(X,1) : PRINT ,A; : NEXT X - 60 END - - Na F5 te hebben gedrukt zal er dit verschijnen : - - 1 2 5 10 17 - - Want 0*0+1 = 1 - 1*1+1 = 2 - 2*2+1 = 5 - 3*3+1 = 10 - 4*4+1 = 17 - - P.S. I.P.V de A in DEF FNA kunt u ook een andere variable - gebruiken als U meerdere vergelijkingen wilt - invoeren. - De A in .=FNA moet dan natuurlijk ook worden - vervangen. - - - - ON INTERVAL= GOSUB - - Dit commando springt om de ID interrupts naar . - Bij 1 interrupt (letterlijk onderbreeking) wordt om de 1/50 - of 1/60 seconde naar een bepaalt adres gesprongen. Staat hier - een z.g.n. RET dan gebeurt er niets, andersdan wordt naar de - gedefinieerde plaats (regelnummer) gesprongen. (zie ook de - ML cursus #7). - Bij dit commando horen nog 3 commando's nl. : - - INTERVAL ON : Het commando wordt in werking gebracht (na - iedere ID interrupts wordt er naar het regel- - nummer gesprongen.) - - INTERVAL OFF : Het commando ON INTERVAL wordt gestopt. - - INTERVAL STOP : Het commando ON INTERVAL wordt genegeerd. - Als U nu weer INTERVAL ON wordt gedaan dan - zal er verder worden gegaan waar is - genegeerd. - - Dit commando is zeer geschikt om een regelmatige klok op te - laten lopen , zie het voorbeeld hieronder : - - 10 'VB. van interval klokje - 20 ' - 30 TIJD=300 - 40 ON INTERVAL=60 GOSUB 80 - 50 INTERVAL ON - 60 A$=INKEY$ : IF A$<>CHR$(13) THEN 60 ELSE END - 70 'INTERVAL - 80 LOCATE 0,0 : PRINT TIJD : TIJD=TIJD-1 - 90 IF TIJD<0 THEN END ELSE RETURN - - - Tot slot nog het INSTR commando : - - A=INSTR(B,A$,B$) : In A komt te staan het hoeveelste - karakter van A$ gelijk is met het - eerste karakter van B$. Er wordt gezocht - vanaf plaats B. Als B niet wordt ingevuld - (A=INSTR(A$,B$)) dan wordt vanaf het - eerste karakter in A$ gezocht. - - Bijvoorbeeld : - - PRINT INSTR("ABCD","A") - 1 - - PRINT INSTR(2,"ABCD","A") - 0 - - PRINT INSTR("ABCD","E") - 0 - - 10 CLS : PRINT "WILT U EEN GETAL INVOEREN ? (J/N)" - 20 A$=INKEY$: IF INSTR("JjNn",A$)>0 THEN 30 ELSE 20 - 30 A=INT((INSTR("JjNn",A$)+1)/2) : IF A=1 THEN PRINT "JA" - 40 IF A=2 THEN PRINT "NEE" - 50 END - - Er wordt dus gekeken of A$ in "JjNn" zit. Zo ja , dan staat - geeft de INSTR : - als A$ = "J" ; 1 , A=INT((1+1)/2)=1 - als A$ = "j" ; 2 , A=INT((2+1)/2)=1 (INT(1.5)=1) - als A$ = "N" ; 3 , A=INT((3+1)/2)=2 - als A$ = "n" ; 4 , A=INT((4+1)/2)=2 (INT(2.5)=2) - - De toepassing van INSTR is vooral handig, als er heel veel - mogelijkheden zijn. M.b.v. ON (INSTR(A$,B$)) GOSUB, kan dan - naar de subroutines van iedere letter gegaan worden. - - - - - Dit was het weer voor deze keer. De volgende keer zoals - gezegd de laatste SPRITES en we gaan eens kijken hoe je de - computer kunt laten denken !!! - - De basic-files zijn ingepakt. Je kunt ze uitpakken met - het bekende programma PMEXT.com. Ga dus eerst naar MSX-Dos - en typ: PMEXT A:BASICC.PMA B:*.* - Pmext staat op deze FutureDisk! - - Tot de volgende keer . - - TOM WAUBEN - - P.S. Heeft U nog vragen over deze cursus of zit u gewoon met - een probleem over BASIC , bel dan gerust naar : - - 046-758100 (na 15.00 u.) - - P.P.S Lees ook de EXTRA SEB op deze disk. (deze gaat - over de VDP-registers). - - - - SPECIAL EFFECTS BASIC #4+ - ------------------------- - - EXTRA *** EXTRA *** EXTRA *** EXTRA *** EXTRA *** EXTRA - - - Jazeker !! Deze keer een EXTRA SEB, om eens wat meer - tegemoet te komen aan de wensen om BASIC wat algemener te - nemen, immers BASIC heeft veel meer mogelijkheden. Daarom - deze EXTRA rubriek. - - Deze keer worden een aantal VDP-registers uitgediepd, met - name de registers 13 en 14. - - - VDP ... - +++++++ - - In BASIC bestaan 1 commando om in de VDP te schrijven of te - lezen ,nl. - - VDP()= - - Hierbij is het registernummer en de aarde. Bij - deze VDP-registers worden altijd een aantal bits geset, om - de gewenste uitwerking te krijgen. - - De VDP (letterlijk Video Display Processor) bepaalt het - uiterlijk van het scherm. De registers hebben dus allemaal - (direct of indirect) invloed op het scherm. Hieronder ziet u - een lijst van de belangrijkste VDP-registers in SCREEN 0. - Alleen register 24 is voor screen 5 t/m 12. - Alle VDP-registers bespreken zou alleen maar langdradig - worden. - - - VDP(7) : Bevat de (1e) voorgrond en achtergrond kleur. - De eerste 4 bits bevatten de voorgrondkleur en de - laatste 4 de achtergrondkleur. - - Bijvoorbeeld : - - VDP(7)=&b00011111 '= COLOR 1,15 (&b0001=1,&b1111= - 15) - - - VDP(9) : De vierde bit van register 9 bepaalt of sprites wel - of niet afgebeeld worden op het scherm. Als deze - geset is, worden ze wel afgebeeld , anders niet. - - - VDP(10) : Hiermee kan de frequentie worden bepaald (50 of 60 - Hz.). Als bit 2 geset is dan is de frequentie 50 - Hz., anders 60 Hz. - - Bijvoorbeeld : - - VDP(10)=&b00000000 'dit is 60 Hz. - - VDP(10)=&b00000010 'en dit 50 Hz. - - - VDP(13) : Dit is ��n van de leukste VDP-registers, samen met - VDP(14). - Het bepaald de tweede voor- en achtergrond kleur - van het scherm. - - Bijvoorbeeld : - - VDP(13)=&b00101110 '2e voorgrond = 2 (&b0010) en - 2e achtergrond =14 (&b1110) - - - VDP(14) :Bepaald hoe lang voor- en achtergrond 1 en hoelang - voor- en achtergrond 2 te zien zijn. - - Deze 2e kleur in screen 0 is alleen te gebruiken - als BLOKKEN. Over iedere positie van het scherm - kan een blokje worden gezet. Voor ieder blokje - staat een bit in V-ram. Deze reeks bits lopen - van adres &h800 to &h905. - - Het is dus mogelijk om 4 kleuren in screen 0 te - krijgen. Dit is erg handig bij allerlei - toepassingen, zoals een menu-balkje (zie SEBMENU op - deze disk). - - Nog een handige functie bij VDP(14) is dat er zelf - bepaald kan worden hoe lang de 1e voor- en achter- - grond en hoe lang de 2e voor- en achtergrond wordt - laten zien. Er kan dus een knipper effect worden - gecre�rd. De eerste nibble (de eerste 4 bits) geeft - aan hoelang de 2e kleuren en de tweede nibble geeft - aan hoeland de 1e kleuren op het scherm staan. * - - Dus bij VDP(14)=&b11110000 zullen altijd de tweede - kleuren op het scherm staan. - - Leuk is dan het knipperen altijd blijft doorgaan, - ook onder het laden. (zie het programma EXTRA.BAS) - - - Bijvoorbeeld : - - 10 SCREEN 0 - 20 FOR I = &H800 TO &H905 : VPOKE I,0 : NEXTI 'WIS - ALLE BITS - 30 VPOKE &H800,&B1010101 - 40 VDP(13)=&HF4 'VOORGROND 15, ACHTERGROND 4 - 50 VDP(14)=&H55 'KNIPPER EVEN LANG 5x 2e KLEUREN, - 5x 1e KLEUREN - 60 GOTO 60 - - * Met "1e kleuren" worden bedoeld de standaard kleuren - Met "2e kleuren" worden de kleuren gezet met VDP(13) - bedoeld. - - - VDP(19) : Dit register is identiek aan SET ADJUST (X,Y). - De Y is bij dit register de eerste nibble, de X - de tweede. Het verschil met SET ADJUST is dat - VDP(19) niet (!) weggesaved wordt in de klokchip. - De ADJUST kan dus veranderd worden, zonder dat de - standaard instelling wordt "aangetast". - - Bijvoorbeeld : - - VDP(19)=&hF1 'komt overeen met : SET ADJUST(1,0) - - VDP(19)=&h27 'komt overeen met : SET ADJUST(-1,-7) - - - VDP(24) : Tenslotte register nummer 24. De werking van dit - register is het beste uit te leggen met een - voorbeeldje, nl. DD-graph. - Als er uit een optie wordt gekozen, scrollt het - hele beeld soepel naar onder. - Dit is ook de werking van VDP(24). Het laat het - beeld in zijn geheel verticaal scrollen. Ook - hiervan staat een leuk voorbeeld in dezelfde file - (EXTRA.BAS). - - Ook van de andere registers zijn voorbeelden. Al deze - voorbeelden staan in 1 file : EXTRA.BAS , op te starten in - het SEBMENU.LDR . - - In de volgende SEB EXTRA zal het toetsenbord met z'n - functies worden uitgediept. - - - TOM WAUBEN diff --git a/Future Disk/075/Turbo-R Basic.md b/Future Disk/075/Turbo-R Basic.md deleted file mode 100644 index 34ffa3b..0000000 --- a/Future Disk/075/Turbo-R Basic.md +++ /dev/null @@ -1,184 +0,0 @@ -Turbo-R basic(1) - - -De tekst Turbo-R basic(2) is ooit al eens geplaatst op -FutureDisk #2 en hebben we herplaatst aangezien de -FutureDisk nu een stuk meer gelezen wordt en het wel bij dit -artikel past. - -In deze tekst ga ik wat dieper in op het commando -CALL PCMPLAY, dus als je dit al geen reet interesseert -dan kun je nu al op duwen. - -Voor wat basisinformatie verwijs ik even naar de andere -Turbo-R basic tekst op deze disk. - -We hebben in het verleden (en ook op deze FutureDisk) nog al -wat sample-liedjes voor de Turbo-R in het demo-menu gehad. - -Waarschijnlijk als je al eens geprobeerd hebt om een liedje -door de hoofdthema's(rode draad deuntjes door een muziekstuk -heen) te samplen en op je Turbo-R na te maken(house-liedjes -dienen zich hier het makkelijkst voor, aangezien deze muziek -heel simpel opgebouwd is;veel herhaling enz.). Heel vaak heb -je niet genoeg aan 64K(basic-tool memory) in het sample- -programma dat bij je Turbo-R zit(dat je trouwens het beste -kunt gebruiken voor samples) aangezien je dan meestal maar te -weinig gesampled krijgt. -Met 128K en dus 2 maal 64K lukt het meestal wel een -fatsoenlijk liedje te maken(kijk maar naar NO LIMIT op deze -disk!). Alleen is het dan een probleem hoe je dit gaat -afspelen in BASIC. Je kunt natuurlijk met de Ramdisk werken -(dus CALL Ramdisk), en daar je samples op zetten. Het -probleem wat je echter dan krijgt, is dat het net iets te -lang duurt voordat je ��n van de samples vanaf de Ramdisk -weer in het gewone RAM gezet krijgt. - -De oplossing is heel simpel! Zet gewoon je twee samples in -het VRAM, daar passen ze allebei net in. Hoe dat kan, zal ik -in het volgende voorbeeld programmaatje laten zien. - -10 SCREEN 5 -20 SET PAGE,0: BLOAD"SAMPLE1.PCP",S -30 SET PAGE,2: BLOAD"SAMPLE2.PCP",S -40 'ZET HIERNA JE AFSPEELROUTINE(S) - -In regel 10 roepen we screen 5 aan(4 pages) waarna we de -eerste sample van 64K op page 0 en 1 zetten en sample 2 op -de tweede en de derde. -Het afspelen van je sample(of delen van de sample) op -normale snelheid gaat dan als volgt: - -CALL PCMPLAY(@BEGINADRES,EINDADRES,1,S) - -,S staat er natuurlijk voor dat het VRAM afgespeeld -wordt en ,S moet je dus niet vergeten te typen. - -Voor beginadres en eindadres geldt echter wel altijd dat -beginadres>eindadres; achteruit afspelen gaat helaas niet. - -De tweede sample begint in ons geval ongeveer bij @65000. - -Tot zover het commando CALL PCMPLAY. Vanaf deze FutureDisk -is de Turbo-R basic corner dus weer tijdelijk terug(wegens -vele verzoeken). De volgende keer ga ik in op de -PCM-outpoorten, waarmee overigens in "NO LIMIT" al mee -geklooid wordt. -Veel plezier met samplen! - -Koen "ik kan ook nog wat anders dan uit men nek lullen" Dols - - -Turbo-R basic (4.0 en 4.1) ----------------------------- - -In deze tekst worden (bijna) alle bevelen die aan basic 2.0 toe- -gevoegd zijn uitgelegt. De MSX-2+ bevelen staan dus ook nog -uitgelegd. -Nadere informatie: In de A1ST zit basic versie 4.0 en in GT -basic 4.1. - -Bevel 1: -Set scroll(X,Y,A,B) - -Het getal dat we voor X invullen geeft aan hoeveel -pixels het beeldscherm horizontaal verplaatst/ver- -schoven wordt.Het beeld dat links verdwijnt komt hier- -bij natuurlijk op de rechterkant van het beeldscherm -weer terug.(De waarde van X kan 0 t/m 511 zijn). -Voor Y geldt hetzelfde principe alleen scrollt U het -beeld hierbij vertikaal(De waarde van Y kan 0 t/m 255 -zijn). -Met de A kan men de eerste en laatste 8 pixels -uitzetten waardoor een vervelend geflikker vermeden -wordt ( Voor A gelden de waarden 0 en 1, wel of niet). -Voor B kan men ook alleen de waarden 0 en 1 invullen -(met zelfde betekenis) en kan men bepalen of men de -pagina achter de afgebeelde pagina mee wil laten -scrollen. - -Bevel 2: -Call Kanji X - -Met dit bevel kan de Kanji mode aangezet worden,waar- -door de karakters veranderen. Voor X kan 0 t/m 3 inge- -vuld worden. Op elk scherm kan nu PRINT gebruikt -worden PRINT #1 heb je dus niet meer nodig. - -Bevel 3: -Call CLS - -Dit bevel heeft dezelfde functie als CLS maar -aangezien CLS niet in de Kanji mode(zie hierboven) -werkt moet men dan dus dit commando gebruiken. - -Bevel 4: -Call ANK - -Met dit bevel wordt de Kanji Mode uitgeschakeld als -deze 'aan' was. - -Bevel 5: -Put Kanji(X,Y),T,K - -Met dit bevel kan een bepaald Kanji-teken en/of een -ander karakter dat de computer kent op het beeldscherm -afgebeeld worden. De X en Y zijn de co�rdinaten op het -beeldscherm van het te plaatsen karakter. De T staat -voor het karakternummer en de K voor de kleur. - -Voorbeeldprogramma dat U alle karakters laat zien: - -10 SCREEN 7 -20 FOR A=8000 TO 30000 -30 PUT KANJI(50,100),A,13 -40 FOR I=1 TO 90:NEXT I -50 NEXT A -60 END - -Bevel 6: -SCREEN X - -Dit bevel is uitgebreider geworden men kan nu voor X -de getallen 0 t/m 12 invullen. Alleen Screen 9 bestaat -(nog) niet. - -Bevel 7: -CALL PALETTE=(K,R,G,B) - -Als de Kanji-mode 'aan' staat werkt het commando -Color=(K,R,G,B) niet meer. -De K staat voor het kleurnummer(0 t/m 15) en met de -waardes R(hoeveelheid rood ,0 t/m 7),G(hoeveelheid -groen,0 t/m 7) en B(hoeveelheid blauw,0 t/m 7) kan -deze oorspronkelijke kleur K verandert worden. - -Bevel 8: -MOTOR ON/OFF -De Turbo-R heeft geen kassette-recorder aansluiting -dus deze commando's komen te vervallen. - -Bevel 9: -CALL PCMREC(@BEGINADRES,EINDADRES,kwaliteit,vol.reactie,KB,S) -Voor het opnemen van een sample. -Als beginadres kan men 0-65535 in vullen evenals het -eindadres. Voor kwaliteit kan 0 t/m 3 ingevuld worden. -Volume-reactie houdt in dat de Turbo-R pas reageert -bij een bepaalde hardheid van de klank.Hiervoor kan -men 0 t/m 127 invullen.Voor KB moet men 1 invullen als -men iets geheugen wil sparen. De S kan ingevuld worden -als U wilt dat de sample in het video-geheugen opge- -slagen wordt. - -Bevel 10: -CALL PCMPLAY(@BEGINADRES,EINDADRES,kwaliteit) -Voor het afspelen van een eerder opgenomen sample. -Zie voor informatie bij CALL PCMPLAY - - -Hopelijk heeft deze tekst U wat meer geleerd over basic -3 en 4. Misschien op FutureDisk #3 een vervolg... - - - Koen Dols - diff --git a/Future Disk/10/Machinetaal 10.md b/Future Disk/10/Machinetaal 10.md deleted file mode 100644 index efa7aae..0000000 --- a/Future Disk/10/Machinetaal 10.md +++ /dev/null @@ -1,273 +0,0 @@ ----- MACHINETAAL CURSUS DEEL 10-1 ---- - - - - - - - - - - -Eindelijk heeft de nummering van de FutureDisk dan toch de -machinetaalcursus bijgehaald. Maar ja, wat wil je als de -hoofdredacteur compleet gestoord(NvdR. Komt dat misschien -niet door jou, dat ik zo gestoord ben, Jantje?) is en vanaf -nummer 6 steeds vreemdere nummeringen gaat hanteren. - -Genoeg gekanker... - -Daar we al bijna de complete instructie set van de Z80 hebben -behandeld is de machinetaalcursus eigenlijk dood en zou je -nu moeten kunnen programmeren in mcode. -Het leek ons nu interessant om meer achtergrond informatie -over de verschillende microchips in je MSX te geven. -Daarom beginnen we dan ook met de bespreking van de - ----- Programmable Sound Generator ---- - -De Programmable Sound Generator (kortweg PSG) is de -standaard MSX geluidschip. Deze kun je dan ook in iedere MSX -aantreffen. Het is een AY-3-8910 (of verwante) microchip en -wordt in het MSX-systeem gebruikt voor de BEEP en muzikale -ondersteuning. Ons peesgeetje kan de volgende dingen: - -* Via 3 toongeneratoren 4096 verschillende frequenties -weergeven op 16 volumeschalen. -* Met een Envelope generator kunnen instrumenten benaderd -worden. -* Met een Noise generator (Ruis!!!) kunnen drums, explosies -en golven gecre erd worden. - -Dit klinkt misschien allemaal spectaculair en je vraagt je -misschien af waarom al die PSG melodietjes zo "slecht" -klinken. -Het probleem is dat de PSG de envelope en noise generators -niet op meerdere kanalen kan toepassen. Je kunt maar 1 -kanaal op een viool doen lijken, een ander op een drum, maar -er blijft er 1 het monotone PSG geluid voortbrengen dat je -hoort als je in BASIC een PLAY opdracht geeft. -Toch mag je niet klagen. Bedenk dat deze chip (lang) voor -1983 ontwikkeld werd en toen zeer goed was (wel eens een -VIC20 horen dreunen??) en dat spellenmakers als Konami, -Compile, T&E soft en weet ik wie, er toch zeer goede muziek -uit voortbrachten. Muziek van de MicroCabin, die zowel PSG -als FM-Pac gebruikt, klinkt soms zelfs als MIDI muziek. - -Nu ongeveer de mogelijkheden van de PSG zijn opgesomt kunnen -we eens gaan kijken naar de meer programmatische kant (wat -een woord!!) oftewel HOE KRIJG IK D'R GELUID UIT ???? - -De communicatie tussen de Z80 en de PSG verloopt via de I/O -poorten #A0 t/m #A2. - -I/O poorten ??? Oke, bijna alles hadden we behandeld: - -Input/Output poorten zijn de verbindingen van de Z80 met z'n -hulpchips zoals de diskdrive, VDP, PSG etc. -Je kunt je dit het beste voorstellen als mannetjes die met -touwtjes aan elkaar zitten. Als het belangrijkste mannetje -(de Z80 dus) een ruk aan het touw geeft (een stroompje -stuurt) gaat het mannetje dat aan het touw vastzit aan de -hand van de sterkte van de ruk een handeling uitvoeren. - -De Z80 heeft 256 van deze touwtjes (0 t/m 255) en kan -daarmee de hele MSX naar z'n hand zetten (een soort -dictatortje dus)(NvdR. Zoiets als mij?). Niet alle poorten -zijn bezet, een aantal is nog gereserveerd voor toekomstige -uitbreidingen. - -Je kunt de I/O poorten aansturen met de volgende Z80 -instructies: - - ---- Output instructies ---- - - -OUT (n),A - -* Deze instructie stuurt de inhoud van A naar poort n. -n kan een waarde hebben van 0 tot 255. - -OUT (C),r - -* Deze instructie stuurt de inhoud van register r naar -de poort waarheen het C-register verwijst - -OTDR (OuTput Decrement Repeat) - -* Stuurt de inhoud van het adres waar HL naar verwijst -naar de poort waar register C heen verwijst. HL wordt -daarna met 1 verlaagd. Het register B, dat als teller -gebruikt wordt, wordt met 1 verminderd. Zolang B niet -nul is wordt de instructie herhaald. - -OTIR (OuTput Increment Repeat) - -* Doet hetzelfde als OTDR alleen wordt het HL register -nu verhoogd i.p.v. verlaagd. - -OUTD (OUTput Decrement) - -* Doet weer hetzelfde als OTDR alleen wordt de -instructie nu niet herhaald totdat B gelijk aan nul -is. Register B wordt gewoon verlaagd. - -OUTI (OUTput Increment) - -* Gelijk aan OUTD, alleen wordt HL verhoogd. - - - ---- Input instructies ---- - - -IN A,(n) - -* Omgekeerde van OUT (n),A. De Z80 vraagt nu een waarde -van het randapparaat. In register A komt nu de waarde -van de met n gespecificeerde poort. - -IN r,(C) - -* Register r wordt geladen met de waarde van de poort -waar register C naar verwijst. - -INDR (INput Decrement Repeat) - -* Tegenovergestelde van OTDR. - -INIR (INput Increment Repeat) - -* Tegenovergestelde van OTIR - -IND (INput Decrement) - -* Tegenovergestelde van OUTD - -INI (INput Increment) - -* Tegenovergestelde van OUTI - - -Gewapend met deze informatie zijn we klaar om de I/O poorten -voor de PSG te bestormen. -(Maar dat doen we in tekst 2) - ----- MACHINETAAL CURSUS DEEL 10-2 ---- - -(Ok�, maak de borst maar nat,we moeten de PSG bestormen!) - - - - - - - - - -In poort #A0 moet je het registernummer zetten dat je wilt -onderzoeken. Met poort #A2 kun je de inhoud vervolgens -lezen en met poort #A1 kun je de inhoud veranderen. - -Huh ?? Registers ?? De PSG ??? - -Ja, ook hulpchips kunnen registers hebben net zoals de Z80. -Een hulpchip is namelijk een eigen processor. De Z80 kan -alleen via een paar registers commando's geven aan een -hulpchip. Als je de PSG een toon wilt laten voort brengen -moet de Z80 eerst de commando's voor die toon doorsturen, -maar daarna neemt de PSG het over en blijft zo'n toon -klinken totdat het Z80 het commando voor "uit" geeft. - -In de volgende cursus zullen we dieper ingaan op de -registers van de PSG en hun functie. We sluiten dit keer af -met een explosie geluidje in machinetaal... luistert en -huivert. -;EXPLOSIE.GEN -;(C) Michiel Visser - - DB #FE ;Header voor GEN80 - DW ST,EN,ST ;Bij WBASS2 overbodig - - ORG #C000 - -ST: - XOR A ;a=0 - LD E,0 - CALL WRTPSG - LD A,1 - LD E,5 - CALL WRTPSG - LD A,2 - LD E,0 - CALL WRTPSG - LD A,3 - LD E,13 - CALL WRTPSG - LD A,4 - LD E,255 - CALL WRTPSG - LD A,5 - LD E,15 - CALL WRTPSG - LD A,6 - LD E,30 - CALL WRTPSG - LD A,7 - LD E,0 - CALL WRTPSG - LD A,8 - LD E,16 - CALL WRTPSG - LD A,9 - LD E,16 - CALL WRTPSG - LD A,10 - LD E,16 - CALL WRTPSG - LD A,11 - LD E,0 - CALL WRTPSG - LD A,12 - LD E,5 - CALL WRTPSG - LD A,13 - LD E,0 - CALL WRTPSG - - LD B,255 -WACHT: ;even wachten - PUSH BC - POP BC - DJNZ WACHT - - LD A,12 - LD E,56 - CALL WRTPSG - LD A,13 - LD E,0 -WRTPSG: - OUT (#A0),A ;Register - LD A,E - OUT (#A1),A ;Data Write !! - RET -EN: - END - -Misschien is het je al opgevallen dat de data veel -overeenkomst vertoont met de BASIC opdracht SOUND. In weze -doet SOUND niets anders dan het weg"outen" van de waardes -naar de PSG. Zo zie je maar hoe machinetaal georienteerd de -BASIC wel niet is !! - -Overigens is de routine WRTPSG rechtstreeks uit de BIOS -gehaald. We hebben ze even uitgetikt om het OUT commando te -verduidelijken. - - Rest ons nog de ASCII en Michiel Visser te - bedanken voor hun medewerking. - - Veel programmeerplezier van: - - Jan Willem van Helden - en Ruud Gelissen - diff --git a/Future Disk/10/Special Effects BASIC 5.md b/Future Disk/10/Special Effects BASIC 5.md deleted file mode 100644 index eb4d209..0000000 --- a/Future Disk/10/Special Effects BASIC 5.md +++ /dev/null @@ -1,174 +0,0 @@ - SPECIAL EFFECTS BASIC 5 ??? - --------------------------- - - Helaas , maar deze keer geen SEB...... Dit zou een dubbel - jubileum moeten worden (FD 10 en SEB 5) maar ik heb geen - tijd gehad om de nodige voorbeelden te schrijven en me te - verdiepen in het hoe en wat om de computer te laten - "denken" (dit zou dus het onderwerp zijn.) en VECTOR MANIA - (zie elders) nam (en neemt) veel tijd in beslag. - - Maar niet getreurd!!(NvdR. Nee, natuurlijk niet!!) Op deze - disk staat de goede versie van de SEB manual. Hoe u deze - ingepakte file moet uitpakken ziet u in de file "SEBPATCH.LDR" - die u kunt laden vanuit het software menu. - - De volgende keer dus een (lange) SEB over het denken van de - computer en om deze tekst toch niet heel afgezaagd te maken - is hieronder toch nog een (mini) SEBje .... - - - SEB vier drievierde - ------------------- - - Deze keer alleen de behandeling van de twee moeilijkste - diskbasic commando's : - - DSKI$ en DSKO$ - - en de RAMdisk van de MSX wordt eens besproken. - - - DSKI$ - ----- - Dit is een afkorting van DISK INPUT (STRING). Met dit - commando kan er informatie van een disk worden gelezen. De - gehele syntax is : - - A$=DISK$(A,B) A is het nummer van de drive en B is het - sectornummer. Ik ga nu niet verder in op de - indeling van sectors, tracks etc. Kijk eens in - een MCCM, daar staan vaak teksten over de - opbouw van een disk. B moet positief zijn en - mag niet groter dan 1440 worden voor - gewone 80 tracks diskette. Voor een harddisk - kan dit getal varieren van 0 to 65535. Om A - uit te "rekenen" kan de volgende regel worden - ingetypt : - - PRINT ASC("A:")-64 'VUL VOOR A: DE DRIVE IN - 1 - - Als u dus van drive B: wilt lezen moet A 2 zijn. - - De informatie van de gewenste SECTOR staat NIET (!) in A$, - maar wordt opgeslagen in het RAM. Om deze te lezen moet u - het volgende programma in typen : - - 10 A$=DSKI$(1,0)'DRIVE A SECTOR 0 - 20 A=PEEK(&HF351)+256*PEEK(&HF352) 'HIER STAAT HET ADRES VAN - DE BEGINPLAATS VAN DE GELEZEN DATA - 30 FOR I=0 TO 100 '100 KARAKTERS ZOEKEN, DIT KAN VERANDERD - WORDEN. - 40 PRINT CHR$(PEEK(A+I)); : NEXT I 'LAAT HET KARAKTER ZIEN - WAT OP DE DISK OOK STAAT. - 50 END - - U ziet dat dit erg omslachtig is, maar in A$ zou het niet - passen, omdat in een string nu eenmaal maar 255 karakters - kunnen en in een sector 512. - - DSKO$ - ----- - - Om op een disk iets rechtstreeks te schrijven is er het - commando DSKO$. Dit is precies hetzelfde als DSKI$. Maar de - syntax is nu : - - DSKO$(A,B) Waarbij A en B hetzelfde betekenen als bij - DSKI$. Dit commando schrijft de informatie van - dezelfde adressen waar bij DSKI$ van werd - gelezen naar disk. - Als u deze informatie veranderd, kunt u dus ook - zelf iets op de sectors schrijven. - - In het onderstaande voorbeeldje wordt de naam van deze cursus - op sector 20 van drive B: geschreven. (LET OP , in sector 0- - 17 staat informatie van de disk. Gebruik bij experimenteren - een lege disk, anders zou het wel eens verkeerd met bv. de - FAT kunnen aflopen !) - - 10 A$="SPECIAL EFFECTS BASIC NUMMER VIER DRIE VIERDE" - 20 A=PEEK(&HF351)+256*PEEK(&HF352) - 30 FOR I=1 TO LEN(A$) 'POKE A$ OP ADRES A EN VOLGENDE - 40 POKE A+(I-1),ASC(MID$(A$,I,1)) - 50 NEXT I - 60 DSKO$(2,20) 'SCHRIJF OP SECTOR 20 VAN DRIVE B - 70 END - - Als u nu het vorige programmaatje aanpast om van drive B op - de 20e sector te lezen (A$=DSKI$(2,20)) dan zult u zien dat - er de tekst van regel 10 in de 2e listing verschijnt. - Experimenteer gerust , maar wel met een lege disk !!! - (Wij zijn niet aansprakelijk voor de gevolgen, van onkundig - gebruik!) - - RAMDISK - ------- - - Jazeker , ook u MSX 2 heeft een RAMDISK ! Maar helaas is - deze niet zo uitgebreid als bv. de RAMDISK (H:) van de - Dos-2 Cartridge. - Er zijn een aantal commando's speciaal voor de RAMDISK, maar - er zijn ook veel gebreken. Op het laatste komen we later nog - even terug. - - CALL MEMINI Dit "maakt" de RAMDISK aan. Als het goed is - veschijnt er als u RETURN drukt : - - 32000 bytes allocated - - U ziet dat deze RAMDISK 32000 bytes (zo'n 31 KB.) vrij - maakt. Hierop kunt u laden en saven door simpel i.p.v. het - disknummer MEM: te typen. Als u bv. de file NAAM.EXT op de - RAMDISK wilt saven typt u : - - SAVE"MEM:NAAM.EXT" - - Dit is precies hetzelfde met laden. Maar als u de - inhoudsopgave wilt zien, dan gaat dit NIET met - FILES"MEM:*.*" !!! Daarvoor is een appart commando evenals - KILL en NAME : - - CALL MFILES Laat u de inhoudsopgave van de RAMDISK zien - CALL MKILL("") Verwijderd een bestand van de RAMDISK - CALL MNAME(""as"") NAMED een bestand van de - RAMDISK. - - LET OP DE HAAKJES BIJ CALL MKILL EN CALL MNAME !!!!!!!!!!!! - - Dit zijn alle commando's die er zijn. Om tijdelijk BASIC - programma's te saven is dit een goede oplossing maar na een - RESET is alles weg !!!!!! - - Toch is het niet allemaal rozegeur en maneschijn wat deze - RAMDISK betrefd. Als we een ML file willen laden of saven - dan gaat dit niet om de simpele reden dat je geen MEM: kunt - typen bij het BLOAD-en BSAVE commando (er verschijnt - dan een foutmelding). - - Maar nog een groter nadeel is het ontbreken van MEM: bij - het COPY commando. Door deze twee gebreken is het dus - onmogelijk om bv. grafische files te laden en saven en er - kunnen ook geen files effe gecopi erd worden. Daardoor wordt - deze RAMDISK niet vaak gebruikt en daarom wordt er ook niet - vaak over gesproken. Maar voor de basicprogrammeur is deze - RAMDISK toch wel handig. SAVEN en LADEN gaat immers wel en - ook het MERGE commando ondersteund deze interne disk. (NvdR. - Saven en Laden, gaat wel verschrikkekekeklijk langzaam!) - - Let er wel op dat er altijd in het begin CALL MEMINI moet - worden gedaan !! - - P.S. I.p.v. CALL kan ook het kortere _ (laag streepje , - +<->) worden gebruikt. - - - Dit was het weer voor deze keer. De volgende keer zoals - beloofd de echte SEB 5 met veel voorbeelden. Bij deze SEB - zijn geen voorbeelden (ook niet echt nodig, geloof ik)(NvdR: - geloven doe je in de kerk, Tom!) - - Tot de volgende keer , - - TOM WAUBEN diff --git a/Future Disk/11/Machinetaal 11.md b/Future Disk/11/Machinetaal 11.md deleted file mode 100644 index 62b0d8b..0000000 --- a/Future Disk/11/Machinetaal 11.md +++ /dev/null @@ -1,128 +0,0 @@ -���� Welkom bij het 11de deel van ���� -���� ���� -���� de MACHINETAALCURSUS ���� -���� ���� - - ------------------------------------------------------ - - Vorige keer hebben we o.a. de OUT/IN instructies behandeld en - beloofden we al om in dit deel uitvoerig op de PSG registers - in te gaan. - Misschien lijkt dat overbodig, omdat de gevorderde BASIC pro- - grammeur dit waarschijnlijk al lang beheerst, maar in - machinetaal is het allemaal veel beter uit te leggen. - BASIC is op het punt van de SOUND intructies namelijk erg - machinetaal geori�nteerd.(dus zonder het te weten zat je ook - vroeger al, je MSX bijna rechtstreeks te besturen d.m.v. - SOUND). - - De PSG registers. - - De PSG (Programmeble Sound Generator) kent 16 verschillende - registers, waarvan de eerste 14 dienen voor het genereren van - geluid. - - R0 en R1 dienen om de frequentie (lees:toonhoogte) te bepalen - van het eerste kanaal. Een frequentie kan bestaan uit 12 Bits - en dus varieren tussen de 0 en 4095 (2 tot de 12de-1). - De onderste 8 bits van deze frequentie moeten in register 0, - de bovenste 4 bits in register 1 gezet worden. - - Dat kan gebeuren met de volgende instructies: - - WRTPSG: EQU #93 ; BIOS - - XOR A ; A=0, weet je nog? - LD E,%xxxxxxxx ; Laagste deel freq. - CALL WRTPSG - LD A,1 ; register 1 - LD E,%xxxx ; Hoogste deel freq. - CALL WRTPSG - - R1 en R2 moet je gebruiken om de frequentie van kanaal B - te veranderen. R3 en R4 zijn dan natuurlijk voor kanaal C. - - Met de registers 2, 4 en 6 wordt dus de grove toon "geset", - met de registers 0,1 en 3 de fijne frequentieverschillen. - - Maar hoe speel ik nu een C op octaaf 4? - Daarvoor kun je het beste de volgende tabel gebruiken: - - 1 2 3 4 5 6 7 8 OCTAAF - ----------------------------------------------- - C - D5D 6AF 357 1AC D6 6B 35 1B - C# - C9C 64E 327 194 CA 65 32 19 - D - BE7 5F4 2FA 17D BE 5F 30 18 - D# - B3C 59E 2CF 168 B4 5A 2D 16 - E - A9B 54E 2A7 153 AA 55 2A 15 - F - A02 501 281 140 A0 50 28 14 - F# - 973 4BA 25D 12E 97 4C 26 13 - G - 8EB 476 23B 11D 8F 47 24 12 - G# - 86B 436 21B 10D 87 43 22 11 - A - 7F2 3F9 1FD FE 7F 40 20 10 - A# - 780 3C0 1E0 F0 78 3C 1E F - B - 714 38A 1C5 E5 71 39 1C E - ------------------------------------------------ - NOOT - - Voor een C op octaaf 4 zet je dus in register 0: &H0AC - en in register 1: &H001 - - Nu we een frequentie kunnen bepalen is het ten eerste van - belang dat de toon een volume toegewezen krijgt, hiervoor - dienen de registers R8 t/m R10. - Slechts de 5 onderste bits zijn van belang. - - Als de 5de bit (=&b000x0000) 0 is, geven de 4 onderste bits - het volume aan, dat daarmee kan varieren tussen 0 en 15. - Is de 5de bit 1 dan worden alle andere bits verwaarloosd en - wordt het volume bepaald door de zogenaamde Envelope Cycle. - - - De Envelope Cycle. - - Met behulp hiervan kan men een toon een bepaald - "aanzwel- en uitsterfpatroon" meegeven. - - In R13 wordt bepaald hoe dit patroon eruit ziet. Daarbij zijn - alleen de onderste 4 bits van belang. - - Men onderscheidt: - - 0-3: uitstervende toon (volume daalt) - 4-7: aanzwellende toon (volume stijgt) - 8 : uitstervende toon, die als hij helemaal weg is weer - opnieuw start (zaagtand vorm) - 9 : idem 0-3 - 10 : respectievelijk uitstervende- en aanzwellende toon - (na volume 15 gaat het volume dalen tot 0 en weer tot 15 - aanzwellen) - 11 : toon sterft uit en gaat daarna op maximum volume. - 12 : aanzwellende toon, die als hij helemaal hard is weer - opnieuw start (zaagtand vorm) - 13 : zwelt aan tot maximum en blijft zo hard. - 14 : idem 10, maar start met aanzwellen i.p.v. met uitsterven. - 15 : idem 4-7 - - Als we een patroon hebben gekozen, kunnen we ook nog bepalen - hoe lang de "aanzwel/uitsterfgolf" duurt m.b.v R11 en R12. - - Alle 16 bits mogen gebruikt worden; hoe hoger het 16 bits - getal hoe langer de golf duurt. - De laagste byte moet je in R11 zetten en de hoogste byte in - R12. Ook hier geldt dus: R12 regelt de grove- ,R11 de fijne - afstelling.. - - Onthoudt goed dat het vullen van de registers R11 t/m R13 - geen nut heeft als in een van de volume registers - (R8 t/m R10) geen 5de bit geset is.(16-31 staat.) - - Voor alle kanalen wordt dezelfde ENVELOPE gebruikt !! - - - Op de PSG kun je niet alleen tonen genereren, ook het maken - van ruis is mogelijk. - In de 5 laagste bits van R6 wordt de ruisfrequentie weer- - gegeven. Deze kan dus varieren tussen 0 en 31, waarbij 31 de - hoogste "ruistoon" is. De ruisfrequentie wordt normaal - gesproken aan alle 3 de kanalen meegegeven. M.b.v. register 7 diff --git a/Future Disk/11/Pascal 1.md b/Future Disk/11/Pascal 1.md deleted file mode 100644 index 66abe3f..0000000 --- a/Future Disk/11/Pascal 1.md +++ /dev/null @@ -1,51 +0,0 @@ - Pascal (1) - ========== - -Men heeft mij gevraagd om een cursus PASCAL te schrijven. En -omdat ik PASCAL een goede, gestructureerde en leuke taal vind, -heb ik ja gezegt. - -Voordat ik ga beginnen met het echte werk, geef ik eerst een -korte inleiding over wat PASCAL precies inhoud. PASCAL is -vernoemd naar de wiskundige Blaise Pascal die van 1623 tot 1662 -leefde. Blaise Pascal was een van de grootste wiskundige die de -wereld gekent heeft. Hij heeft onder andere de fundamenten -gelegd van het kansrekenen. Maar het bekenste wat Blaise Pascal -heeft gedaan (buiten zijn bekende driehoek) is het constru�ren -van een rekenmachine. Deze machine kon veel rekenkundige -berekeningen uitvoeren, en dat terwijl het geheel alleen maar -uit tandwielen en dergelijke bestond (probeer je dat eens voor -te stellen). - -Rond 1970 dook de naam PASCAL (geheel in hoofdletters) weer op. -Dit omdat ene Professor Niklaus Wirth het leuk vond om zijn -zojuist ontwikkelde programeertaal te vernoemen naar Blaise -Pascal. En deze taal is nu h��l bekend. De meeste mensen hebben -er ervaring mee, of hebben er wel van gehoord. Het voordeel van -PASCAL boven BASIC is de gestructureerdheid. Is het verplicht -bij BASIC om commentaar te plaatsen (zeker als iemand anders er -iets van moet begrijpen) bij PASCAL word de helft van de -'documentatie' door de gestructureerdheid van de taal zelf -verzorgd. Hiermee bedoel ik dat je er bij BASIC een spagetie van -kunt maken (met behulp van GOTO-instructies) die niet te lezen -is. Terwijl je bij PASCAL het programma veel sneller doorziet -door het inspringen (word later duidelijk), de grotere -verscheidenheid aan herhalingslussen (WHILE, REPEAT en FOR) en -het (bijna) niet voorkomen van GOTO-instructies. - -Tot zover de inleiding. Nu gaan we dus echt beginnen. Dat echt -beginnen houdt in dat ik de globale structuur van een -PASCAL-programma ga uitleggen. - -De globale structuur van een PASCAL-programma is als volgt : - -PROGRAM programma_naam (INPUT,OUTPUT); - - CONST - {Constante definitie} - - TYPE - {Type definitie} - - VAR - {Variabelen declaratie} diff --git a/Future Disk/12/Pascal 2.md b/Future Disk/12/Pascal 2.md deleted file mode 100644 index 112ae14..0000000 --- a/Future Disk/12/Pascal 2.md +++ /dev/null @@ -1,158 +0,0 @@ - Pascal Cursus (2) - ================= - - - Wat is die Koen toch een etter. Nauwelijks ben ik een PASCAL - cursus begonnen of hij begint al met klagen. Vorige keer had - ik een leuke programmaatje op de disk laten zetten om je CD's - beter op te kunnen nemen, maar nee, voor meneer Dols is het - weer niet goed. - - Koen : Kan ik niet aangeven dat ik een 60 bandje heb? - Jeroen : Nee Koen, dat kan niet, dat was wat veel werk. - Koen : Wat is dat dan voor een stom programma, zorg er maar - voor dat dat volgende keer verbeterd is! - - Tja, en ik als goede onderdaan (Sahib, sahib) heb dat dus ook - maar gedaan. Ik hoop dus maar dat hij dit keer niets te zeiken - heeft.(NvdR: ik heb thuis ook nog 100 minuten bandjes - Jeroen!) - - Maar genoeg over onze sadist Koen. Nu gaan we over naar het - echte werk : programmeren. Als ik mij goed kan herineren, dan - hebben we het vorige keer over de globale structuur van PASCAL - gehad. Nu gaan we het over variabelen hebben. - - Een groot verschil tussen BASIC en PASCAL is dat het in PASCAL - verplicht is om alle variabelen die je gebruikt van te voren - aan te melden en te specificeren. Wat ik hiermee bedoel is dat - je de compiler duidelijk maakt hoe je variabelen heten (jan, - piet of klaas) en wat voor variabelen het zijn. Een variabele - declaratie zou er als volgt kunnen uitzien (de variabele - declaratie moet altijd vooraf gegaan worden door het - gereserveerde woord VAR) : - - VAR - teller : integer; - getal : real; - status : boolean; - - De opbouw van deze declaratie mag wel duidelijk zijn. Eerst - komt er het gereserveerde woord VAR. Op de volgende regels - volgt de naam van de variabele die je gaat gebruiken gevolgd - door een dubbele punt en het type van de variabele. Aan de - naam van de variabele is eigenlijk maar een grote restrictie, - de naam mag geen gereserveerd woord (zoals BEGIN, END, VAR, - etc) zijn. De dubbele punt is verplicht. Het type van de - variabele kan vanalles zijn, maar ik beperk me hier tot de - standaard types : - - - boolean (kan de waarde TRUE of FALSE hebben) - - byte (spreekt voor zich) - - integer (16 bits geheel getal, ook word) - - longint (32 bits geheel getal, ook longword) - - real (een gebroken getal, lengte hangt af van de machine) - - char (een ascii karakter) - - string (een reeks ascii karakters) - - text (een file met ascii karakters) - - De punt-comma op het einde van de regel is verplicht (bijna - alle programma regels in PASCAL worden afgesloten met een - punt-comma). Naast bovengenoemde standaard types kun je ook - zelf types ontwikkelen (dagen van de week bijvoorbeeld), maar - daar kom ik later op terug. Voor ik het vergeet, de laatste 2 - types zouden wel eens niet kunnen werken, daar ze niet vanaf - de eerste PASCAL versies ge�mplementeerd waren. Vanaf versie 3 - of hoger zouden ze echter aanwezig moeten zijn. - - Dan komen we nu bij de toewijzingen. Deze zijn zeer - gemakkelijk : - - getal:=2; - letter:='A'; - teller:=teller+1; - - Bovenstaande voorbeelden zijn erg simpel, maar geven het - principe goed weer. Een toewijzing wordt als volgt opgebouwd: - - Als eerste komt de variabele waar iets aan toegekend moet - worden. Dan volgt een dubbele punt met een "is-gelijk" - teken (spreek := uit als 'wordt'). En als laatste volgt de - waarde die de variabele moet krijgen. Deze waarde wordt - samengesteld zoals in BASIC, met een kleine restrictie: het - type mag (uiteraard) niet wijzigen. Dus als getal eerst een - integer was, dan mag deze niet door 'getal:=1.5' veranderd - worden in een real. Genoemde toewijzing zal resulteren in - een compiler fout of een run time error. - - Naast de gebruikelijke operators (+, -, *, (), AND, OR, XOR, - NOT) zijn er ook nog functies zoals CHR, ORD, ROUND, TRUNC, - ABS, ARCTAN, COS, EXP, FRAC, INT, LN, SIN, SQR, SQRT, etc. De - meeste namen duiden op soortgelijke functies uit BASIC, voor - meer details verwijs ik naar boeken over PASCAL. Genoemde - functies kunnen gewoon gebruikt worden in een toewijzing, als - men er maar aan denkt dat het type van de hele toewijzing - gelijk moet zijn aan het type van de variabele. - - Laatstgenoemde punt impliceerd dat er twee functies moeten - zijn om een getal te delen. Waarom? Omdat delen per definitie - een gebroken getal opleverd en dat dus niet een integer is. - Gehele getallen kunnen echter wel op elkaar gedeeld worden en - daarom is er een speciale functie nodig om integers te delen. - Deze speciale functie is de DIV functie (DIVide). De logisch - bijbehorende functie is MOD (MOD geeft de rest van de deling). - - Zo, dat was het voor deze keer. Maar voor ik jullie weer - verlaat (ooohh) geef ik jullie nog een voorbeeldje en een - opgave om zelf te maken. Van het voorbeeld programmaatje ga ik - niet veel verklappen, bekijk het maar eens en probeer (voor- - dat je het laat uitvoeren) te beredeneren wat het doet. Het - voorbeeld programmaatje staat op de disk onder PASCAL2.PAS (dan - hoeven jullie het niet over te tikken). - - De opgave daar wil ik iets anders mee doen. Als iemand zo gek - is om het te proberen, het op te lossen en de oplossing op te - sturen, dan beloof ik die persoon dat zijn oplossing volgende - keer geplaatst wordt. En om het nog aantrekkelijker te maken - vermelden we de naam van de persoon die de oplossing heeft - ingestuurd (H� Koen, wedje dat nu niemand meer iets instuurt. - Kun je tenminste niet weer kankeren dat je niet alles op de - disk kunt plaatsen wegens plaatsgebrek). - - Zo, genoeg getypt, nu de opgave : - Schrijf een programma dat om 3 netto prijzen van artikelen - vraagt. Bereken aan de hand van die prijzen : De BTW per - artikel, het totaal betaalde BTW bedrag, de totale BRUTO en - NETTO prijs van de drie artikelen. - - Aangezien ik nog niets heb gezegd over in- en uitvoer van - variabelen via toetsenbord en beeldscherm, verwijs ik naar het - voorbeeld programma. Door dit goed te bekijken moet het - mogelijk zijn om iets soortgelijks te construeren. - - Veel plezier en tot volgende keer, - - Jeroen 'KUBIE' Smael - Galopiahof 6 - 6215TK Maastricht - Tel : 043-437778 - - P.S. (1) Om een nieuwe programmeertaal te leren moet je zelf - een heleboel oefenen en uitzoeken, daar leer je - tenslotte het meeste van. Daarom kauw ik niet alles - voor, maar laat een heleboel aan jezelf over. - (2) Boeken die je kunt raadplegen zijn onder de VELE - andere : K.L. Boon / PASCAL voor iedereen / Kluwer / - ISBN 90.201.1425.5 --- Findley / PASCAL Inleiding tot - gestructureerd programmeren / Kluwer / ISBN - 90.201.1991.5 - (3) Let ook op de programmeerstijl die ik in het - voorbeeldprogramma gebruik. Er is geen standaard - voor, maar mijn stijl is wel gestructureerd en dat - bevorderd de leesbaarheid. - (4) Dankzij Koen staat er dus ook een verbeterde versie - van het CD programma op de disk (CD2.PAS / CD2.COM). - Veel plezier daarmee (nog iets te mekkeren, Koen?). - (NvdR: Ja, Jeroen: Bl���������������������������h!) - - C YA @ !! diff --git a/Future Disk/12/Special Effects BASIC 5.md b/Future Disk/12/Special Effects BASIC 5.md deleted file mode 100644 index ae4062f..0000000 --- a/Future Disk/12/Special Effects BASIC 5.md +++ /dev/null @@ -1,205 +0,0 @@ - - �W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W� -W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W - SPECIAL EFFECTS BASIC #5 - �W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W� -W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W - - ���� - ���� - ���� - ���� - - - Na een keer te hebben overgeslagen is er dit keer dan toch - de SEB nummer 5 !!! Door de aloude reden "Ik had effe geen - tijd" heeft de SEB anderhalve editie FutureDisk moeten - overslaan. Maar dit keer is het de vijfde Special Effects en - dat moet gevierd worden !!! - - - LEES VERDER EN HUIVER !!!! - - Op een doordeweekse dag , helemaal uitgeput van 7 uur - schoolslapen moest ik toch maar eens naar de bibliotheek. - Ik moest nog 5 boeken lezen op 2 weken tijd (computer ik te - veel?!). Na alle leuke (????) boekenlijstboekjes te hebben - uitgezocht en de samenvattingsboeken gecopi�erd zag ik mijn - kans om eens te kijken of er nog wat MSX in de rekken, of - liever gezegd, in de computer stond. Al brakend liep ik naar - zo'n gore helemaal-onder-de-nicotineaanslag-zittende PC - (kots,kots) om daar nog na kokhalzend met bibberende vingers - M S X in te tijpen. Na veel geratel en een minuut wachten - (jaa, een PC uit '74) zag ik een aantal boeken verschijnen - maar omdat er na een uur bleek dat er geen in de bibliotheek - aanwezig was dook ik de rekken zelf maar in.... Na veel - zoeken tussen de stoffige Norton Utilities deel 1 tot en met - 100, zag ik een boekje met het opschrift MSX BASIC. - Heel erg blij slaakte ik een paar vreugdekreten, toen - ik me realiseerde dat ik naast de studiezaal stond. Na dat - k*twijf van me af te hebben gegooid en in de hoek gepleurd - zag ik kans om het boekje te pakken en het mee te nemen naar - een stil hoekje. Nadat ik alle drugsspuiten had opgeruimd en - een krant vond om wat van dat rode spul mee af te dekken - (bloed of zo??!) sloeg ik de eerste bladzijde open. 02 1985, - een oud boekje dus, maar toch verder. Na twee lijsten met - verbeteringen te hebben doorgelezen kom ik eindelijk aan bij - de inhoud. De normale zaken worden besproken zoals : hoe zit - een computer in elkaar, wat is MSX, heb je een toetsenbord - bij je MSX?, etc. De volgende bladzijde krijg ik met moeite - opengereten. Daar ligt een zielig muggenkerkhof, de barbaar - die het boek voor mij had, zal wel geen vliegenmepper hebben - gehad .... - Na te hebben gelezen dat MSX een geweldige toekomst tegemoet - zou gaan (ach ja , 1985) en dat iedereen (!!) een MSX zou - gaan kopen , kom ik aan bij het hoofdstuk "PRINT". Hier - wordt het print commando besproken, maar aangezien ik dit - toch al wist, ging ik maar meteen naar APPENDIX P. - In APPENDIX P stonden een aantal leuke korte programmaatjes - die ik U niet wil onthouden dus kijk maar es in 't software- - menu. LET WEL !!! De programma's zijn niet door mij - geschreven maar door de "AUTEUR" van dit boek. Kijk en be- - oordeel zelf .... - Het valt me op dat het octale stelsel uitgebreid besproken - wordt en dat iedere lezer geacht wordt al enige kennis met - binaire getallen te hebben, terwijl het boek (ik citeer) - "Voor velen een eerste kennismaking zal zijn, een kennis- - making waarbij de lezer stellig begrip hoopt te ontmoeten - voor de drempels die hij moet nemen. Voor deze lezers is - dit boek geschreven". - DEBIELE MONGOLE OERSTOMME ACHTERLIJKE IDIOTE OETLUL !!!!!!!! - Na het boek weer inelkaar te hebben geplakt bladerde ik er - nog eens doorheen. Haaa , een "Intermezzo, Kunnen computers - denken??". Verheugd lees ik verder ... om na 3 regels weer - te stoppen ; wat interesseert mij of de mensen 100 jaar - geleden wilden dat er een electronisch brein kwam! - Het boek was nu twee keer zo dik geworden omdat ik 't per - ongeluk buiten in de regen had laten liggen en daarna in de - afwasmachine had gestopt. Ik sloeg het open en zie bij - appendix Z een lijst van alle (!) basiccommando's. Dit staat - tenminste in de inleiding. Zou deze ****schrijver niets eens - van de commando's MKI$,MKD$ etc. hebben gehoord?? En waar - is het gedeelte over het laden en saven van disk. 1985?? - Kom nou, voorin het boek staat beschreven dat er "een - kastje met electronische schijfjes bij de computer kunnen - zitten. Computerproffesionals noemen dit een DISKDRIVE" - NEEEEEEEEEEEEEEE TOCH ?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - Nadat ik geergerd de lijst met foutmeldingen doorlees (ach - ja, tijd te veel ?!) denkend dat hier niets fout kan gaan - (handleiding overschrijven) zie ik dat er een illegal - fuction call wordt gegeven als : 1) negatieve arrayindex, - 2) SQR(-1) / LOG(-1), 3) verkeerd gebruik USR, MID$,etc. - En als ik dan SCREEN 900 intyp ?? ILLEGAL FUCTION CALL. - Met in het achterhoofd dat het boek uit 1985 komt (waarom - lees ik deze crap??) kan ik me er nog net van weerhouden - het boek (wat daar nog van over is) te begraven... - - Omdat we geen WC-papier hadden en ik het boek toch niet - meer las konden we iedere bladzijde gebruiken als - WC-blaadje. Alleen de kaft was nogal hard ...... - De kaft heb ik daarna maar lekker baldadig op de stoep - gelegd , een kan benzine gehaald en 't daarin gedompeld en , - ach ja de rest weet U wel! - De bibliotheekaaresse (??????) vroeg niet eens waar het boek - was (of had ik het meegenomen zonder te laten afstempelen?!) - Weer thuis gekomen wist ik eindelijk waar deze SEB over zou - gaan : KUNNEN COMPUTERS DENKEN ?? - - Nou om maar te eindigen met dit (ingekorte) EEN-DAG-UIT-HET- - LEVEN-VAN-EEN-RANDIMBICIEL verhaal, hieronder een verhaaltje - hoe computers kunnen "denken". - - *************** DENK-COMPUTER ????! **************** - - Een computer moet worden gezien als een kastje met enkele - electronische schakelingen en chips die bewerkingen kunnen - uitvoeren. - EEN COMPUTER KAN DUS NOOIT DENKEN - - Maar omdat we de kennis (??!) hebben om een programma te - schrijven kunnen we ons DENKPATROON in de computer invoeren. - Het gaat dus om PATROONHERKENNING en niets anders. Dit - patroon moet worden uitgezocht dus enige voorstudie is nood- - zakelijk. Als je wilt dat de computer een spel kan spelen met - "strategie" dan zal de programmeur een stappenplan moeten - maken waarin staat wat de computer precies moet doen om zo - te winnen. - - Bij het onderstaande programmaatje is dit patroon wel duidelijk - : - 13 lucifers, de som van de weggepakte lucifers moet 4 zijn - want als dit zo is dan blijven er achtereenvolgens 13,9,5,1 - lucifer(s) over. Wie de laatste lucifer over houdt heeft - verloren. - - De computer wint altijd !!. Speel het maar eens ; U zult - zien dat U altijd verliest (LUCIFER.LDR) - �W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W� -W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W - - Kort samengevat : - - 1) Bestudeer spel + strategie - 2) Maak stappenplan (PATROON) - 3) Laat de computer het PATROON HERKENNEN (vertaal 2 in een - programma) - - �W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W� -W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W�W - - Als tweede voorbeeld nemen we een veel moeilijker patroon - nl. dat van BOTER-KAAS EN EIEREN (TIC-TAC-TOE) - - SPELREGELS : - - Er wordt gespeeld in een matrix van 3x3. Het doel is om zo - snel mogelijk drie op een rechte lijn te krijgen. Er mag - niet over een anders heen gezet worden en er zijn 2 spelers - die om de beurt spelen. - Allereerst moet de computer de spelregels kennen. We maken - eerst een versie die alleen de spelregels kent. Het is - altijd goed eerst zo'n "stomme" versie te maken die werkt - omdat de patroonherkenning nogal ingewikkeld is. - We maken eerst alles in screen 0 om het daarna over te - plaatsen in bv. screen 5. Dit is niet zo moeilijk als de - "screen 0 versie" werkt. Bekijk deze list eens ; zie file - "SCREEN0V.BKE" - - We proberen nu een patroon te vinden voor het zetten van de - kruisjes op een stategische manier. Het beste is om in het - midden te beginnen en zo naar buiten te werken. Het is dus - afwachten wat de speler doet. - - Er is ook nog verschil tussen de versie waarbij de speler en - de versie waarbij de computer begint. Om het patroon zelf te - vinden is het spelen van het spelletje (heeel vaak!!) nodig - om het patroon te vinden. Er zijn natuurlijk meerdere - patronen mogelijk (goede en slechte ; daarmee kunnen levels - worden gemaakt : eerst het slechte en dan steeds een beter - patroon). Dit neemt wel veel plaats in beslag!! We beperken - ons nu tot ��n versie, maar dan wel een die de eigenlijke - uitkomst van boter-kaas-en-eiren (altijd) laat uitkomen : - - ALS ER GOED GESPEELD WORDT KAN NIEMAND WINNEN !!!!!!!!!!!!!!! - - De computer zal ook nooit winnen, behalve als de speler een - fout maakt. Het patroon ziet er nogal ingewikkeld uit : - - SPELER BEGINT - ------------- - 1. Kijk of midden vrij is , zo ja , zet in 't midden, anders - zet op een hoek - 2. Kijk waar de speler kan scoren en sluit deze weg af. - 3. goto 2. behalve als de speler een fout maakt en de weg - vrij is om zelf te scoren. - - Dit patroon is vrij eenvoudig omdat het alleen bij de eerste - beurt een speciale zet doet, en anders iedere keer de wegen - afsluit voor de tegenstander. - - De volgende keer volgt de rest van BKE en we gaan het - spelletje EXPLOSIE maken .... - - C YA NEXT TIME !!!! - - T O M " A T L A N T I S " W A U B E N diff --git a/Future Disk/13/Machinetaal 12.md b/Future Disk/13/Machinetaal 12.md deleted file mode 100644 index e39caaa..0000000 --- a/Future Disk/13/Machinetaal 12.md +++ /dev/null @@ -1,145 +0,0 @@ - - ---- Mcode cursus #12 ---- - - ���� ���� - ���� ���� - ���� ���� - ���� ���� - - - De vorige keer geen Mcodecursus, omdat Ruud en ik even een - weekje waren skieen en dus hele andere dingen aan onze kop - hadden dan een mcodecursus.(NvdR: en thuis met twee gebroken - benen op bed lagen) - - Deze keer behandel ik de PSGregisters 14 en 15. - - Deze 2 registers van de PSG worden op de MSX gebruikt voor - het uitlezen van de beide spelingangen, in de volksmond - beter bekend als de joystick-poorten. - - De aansluiting voor de spelingangen zijn 2 vrouwelijke (Ja, - de MSX is dus een zij!!) 9-pins AMP-aansluitingen en zijn - als volgt ingedeeld: - - ************************************* - * * - * *** *** *** *** *** * - * * 1 * * 2 * * 3 * * 4 * * 5 * * - * *** *** *** *** *** * - * * - * *** *** *** *** * - * * 6 * * 7 * * 8 * * 9 * * - * *** *** *** *** * - * * - ******************************* - - Pin nr. Naam Signaal Richting - - 1 FWD IN - 2 BACK IN - 3 LEFT IN - 4 RIGHT IN - 5 +5 V --- - 6 TRG 1 IN/UIT - 7 TRG 2 IN/UIT - 8 OUTPUT UIT - 9 GND --- - - PSG register 14 kan alleen gelezen worden. De bits van dit - register hebben de volgende betekenis: - - Bit 7 Cassete-ingangsignaal - Bit 6 ???? - Bit 5 invoersignaal pin 7 - Bit 4 invoersignaal pin 6 - Bit 3 invoersignaal pin 4 - Bit 2 invoersignaal pin 3 - Bit 1 invoersignaal pin 2 - Bit 0 invoersignaal pin 1 - - PSG register 15 kun je zowel lezen als schrijven. Voor de - betekenis van de bits geldt: - - Bit 7 ???? - Bit 6 keuze spelingang 1 of 2 (1=ingang 2) - Bit 5 uitvoersignaal pin 8 ingang 2 - Bit 4 uitvoersignaal pin 8 ingang 1 - Bit 3 uitvoersignaal pin 7 ingang 2 - Bit 2 uitvoersignaal pin 6 ingang 2 - Bit 1 uitvoersignaal pin 7 ingang 1 - Bit 0 uitvoersignaal pin 6 ingang 1 - - - Deze registers kun je gewoon gebruiken als normale PSG - registers en je kan dus gewoon via poort #A0 het nummer van - het register schrijven (14 of 15) en dan met poort #A1 een - waarde inschrijven of met poort #A2 de waarde van het - register lezen. - - Wat hebben we nu aan deze wetenschap ??? - - Via deze 2 spelingangen kunnen we joysticks (genotsknotsen), - muizen, touchpads, lichtpistolen etc. etc. op de MSX - aansluiten. Ook kan er zo een verbinding tussen 2 - MSXcomputers tot stand worden gebracht, je kunt immers - lezen en schrijven (in beperkte mate) via deze poorten. Er - bestaat zelfs een boek dat "Kreatief met Spelingangen" - omgaat: Electronicaprojecten voor MSX-Computers. Dit boekje - ligt nog voor geen tientje bij de meeste "de Slegte"- - boekhandels. Wie weet brengt dit nog iemand op het idee om - een SNES-scope via de spelingangen te besturen. - - Tot slot nog een listinkje voor de Codefreaks: - - - ORG #C000 - - DB #FE - DW ST,EN,ST - - ;PSG Lees - ;Leest de inhoud van ingang 1 en 2 - - ST: - DI - LD A,15 - OUT (#A0),A - LD A,%00000000 - OUT (#A1),A ; Ingang 1 aanzetten - LD A,14 - OUT (#A0),A - IN A,(#A2) ; Ingang 1 lezen - LD (STCK1),A - LD A,15 - OUT (#A0),A - LD A,%01000000 - OUT (#A1),A ; Ingang 2 aanzetten - LD A,14 - OUT (#A0),A - IN A,(#A2) ; Ingang 2 lezen - LD (STCK2),A - EI - RET - STCK1: DB 0 - STCK2: DB 0 - EN: END - - Wil je echt nog wat meer over deze registers te weten komen - dan raad ik je aan om eens de BIOSroutines #D5,#D8 en #DB te - disassemblen. Dit zijn namelijk respectievelijk de - Joystickuitlees, de Joystickknoppenuitlees en de muisroutine - van de MSX. - - Mijn grote dank gaat uit aan A.Rensink voor de informatie - over dit onderwerp. - - - Veel programmeerplezier van: - - Jan-Willem van Helden - en Ruud Gelissen - - P.S. Ja, sorry dat dit zo'n korte cursus is, maar Hegega - moet Bet Your Life nog afmaken en dus staat de programmeer- - cursus effe op een wat lager pitje ..... diff --git a/Future Disk/13/Pascal 3.md b/Future Disk/13/Pascal 3.md deleted file mode 100644 index 2323138..0000000 --- a/Future Disk/13/Pascal 3.md +++ /dev/null @@ -1,153 +0,0 @@ - * Pascal (3) * - - - Welcome to the third PASCAL course. Ofwel, hallo, dit is de - derde PASCAL cursus op de FD. Het mag dan wel FD #13 zijn, - maar aangezien de PASCAL cursus pas zijn derde nummer ingaat - zou alles dus helemaal okie dokie moeten zijn. Wat een gezeur - h�! Ik zal maar beginnen, voor ik nog meer onzin uitkraam. - - Vorige keer heb ik het over Koen gehad (helemaal in het begin) - en ja hoor, hij had weer iets te zeiken, dus nu even mijn - antwoord: "Ja Koen, je kunt ook 100 minuten bandjes door mijn - programma laten uitrekenen.". Zo, dat is ook weer opgelost. - (NvdR: ja stomme ezel, dat had ik ook al door!) - - Nu even echt serieus. Deze keer ga ik lussen bespreken. In - PASCAL zijn drie soorten lussen: FOR-TO-DO, REPEAT-UNTIL en - WHILE-DO. Uit de namen kan al ��n en ander afgeleid worden. - Maar ik zal de verschillende lussen met een voorbeeld - behandelen. - - Stel ik wil de getallen 1 t/m 10 op het scherm toveren. Hoe - doe ik dat? Hier komen de drie mogelijkheden: - - FOR-TO-DO: - - PROGRAM ForNext (input,output); - - VAR - teller : integer; - - BEGIN - FOR teller := 1 TO 10 DO - writeln(teller); - END. - - REPEAT-UNTIL: - - PROGRAM RepeatUntil (input,output); - - VAR - teller : integer; - - BEGIN - teller := 0; - REPEAT - teller := teller + 1; - writeln(teller); - UNTIL teller = 10 - END. - - WHILE-DO: - - PROGRAM WhileDo (input,output); - - VAR - teller : integer; - - BEGIN - teller := 0; - WHILE teller < 10 DO - BEGIN - teller := teller + 1; - writeln(teller); - END; - END. - - Dat waren ze. Maar nu de uitleg. In het eerste voorbeeld - (FOR-TO-DO) zie je, dat de variabele "teller" van 1 t/m 10 zal - lopen. Er staat tenslotte dat de teller zal lopen van 1 tot en - met 10, en zolang moet je teller afdrukken. Een FOR lus kan - niet worden onderbroken (voor de echte crack wel, maar dat is - met een GOTO en dat is weer niet gestructureerd en dus niet - netjes). Een FOR lus loopt altijd van onder- tot bovengrens. - Nu denk je natuurlijk: Ik wil ook van 10 naar 1 kunnen lopen, - dat kan, maar dan moet je DOWNTO in plaats van TO gebruiken. - Voor de goede orde: Als de ondergrens groter is dan de - bovengrens (FOR teller := 2 TO 1 DO) dan gebeurt er dus - niets. - - Het tweede voorbeeld (REPEAT-UNTIL) werkt heel anders. Hier - wordt de lus op een bepaalde conditie verlaten. In het - voorbeeld staat dan ook HERHAAL ... TOTDAT teller=10. Zolang - teller niet 10 is, gaat de lus door. Probeer maar eens wat er - gebeurt als je de regel "teller := teller + 1;" weglaat. Je - zult zien dat de lus eindeloos doorgaat; teller wordt ook - nooit 10. - - Het verschil met het tweede en derde voorbeeld is eigenlijk - minimaal. Ook hier wordt de lus verlaten bij een bepaalde - conditie (teller=10), alleen wordt hier eerst gecontroleerd en - daarna pas beslist of de lus doorlopen moet worden. Het grote - verschil is dan ook dat de REPEAT-UNTIL minimaal 1 maal - doorlopen wordt, terwijl dat bij de WHILE-DO niet het geval - is. - - Zo, dat was een snel overzicht van de lus functies in PASCAL. - En nu maar oefenen. Tja, ik kan het niet vaak genoeg zeggen, - veel oefenen, anders leer je het niet. Ik zal, hoewel vorige - keer niemand een reactie heeft gegeven(gek h�) (NvdR: ligt - gewoon aan jou!), ook deze keer wat opdrachten geven. - - OPDRACHTEN: - (1) Maak een programma dat alle mogelijke combinaties van 4 - (hoofd)letters op het scherm zet (doe dit met alleen - FOR-TO-DO, REPEAT-UNTIL of WHILE-DO lussen). - (2) Maak een programma dat alle priemgetallen tot een - ingegeven getal berekend (doe ook dit met alleen - FOR-TO-DO, REPEAT-UNTIL of WHILE-DO lussen). - - Voordat jullie kunnen beginnen moet ik nog even snel wat - uitleggen over compound-statements. In PASCAL is het namelijk - zo, dat na bepaalde opdrachten (FOR-TO-DO, WHILE-DO, - IF-THEN-ELSE) maar ��n opdracht mag staan. Bij de FOR-TO-DO - lus mag dus niet staan: - - WHILE teller < 10 DO - write(teller); - teller := teller + 1; - - De opdracht "write(teller)" is namelijk 1 opdracht en de - volgende opdracht "teller := teller + 1" zou pas worden - uitgevoerd als de WHILE-DO lus voorbij is (nooit(!)). Vaak is - het echter noodzakelijk dat meerdere opdrachten in een lus - worden uitgevoerd. De oplossing hiervoor is het compound- - statement. Een compound-statement is een heleboel statements - omgeven door een BEGIN en een END. Het voorbeeld zal dus - worden: - - WHILE teller < 10 DO - BEGIN - write(teller); - teller := teller + 1; - END; - - Bij het bovenstaande programma zal alles wel naar wens - verlopen. Samenvattend komt het er op neer dat als je bij - lussen (REPEAT-UNTIL is hier de bevestigende uitzondering) - meerdere statements wil laten uitvoeren, dat je die statements - moet laten voorafgaan door BEGIN en eindigen met END. - - Zo, met bovenstaande informatie moet je in staat zijn om de - zes opdrachten te maken. - - Veel plezier, - - ���� Jeroen "KUBIE" Smael - ���� Galopiahof 6 - ���� 6215TK Maastricht - ���� Telefoon : 043-437778 - - C YA @!! - diff --git a/Future Disk/14/Pascal 4.md b/Future Disk/14/Pascal 4.md deleted file mode 100644 index e9a4c14..0000000 --- a/Future Disk/14/Pascal 4.md +++ /dev/null @@ -1,150 +0,0 @@ - - PASCAL (4) - ========== - - Programmeren is masochisme, maar wat is het lekker(NvdR:??). - Nou ja, als je aan het programmeren BENT niet, maar als het - werkt en die kl*t* machine doet eindelijk precies wat JIJ - wilt, dat is pas een hoogtepunt. Waarom vertel ik dit - allemaal? Als eerste omdat ik een reactie van Koen wil - uitlokken (h� etter, waar ben je)(NvdR: hiero!) en als - tweede een meer belangrijke reden (Koen is tenslotte niet - belangrijk)(NvdR: moet je iemand horen!) om je te stimuleren - om toch vooral door te gaan, want uiteindelijk lukt het - wel[ (dat MSX'je kan veel meer dan je denkt). - - Deze vierde aflevering van mijn PASCAL cursus is gewijd aan - PROCEDURE's en FUNCTION's. In elke programmeertaal ontstaat op - een bepaald moment behoefte aan funkties en procedures. - Waarom? Nou, gewoon, omdat je geen zin hebt om een bepaald - stuk code dat je vaker nodig hebt (bijvoorbeeld een invoer - routine) ook vaker in te tikken. Als je het geheel ��n keer - hebt ingetikt, dan wil je het vaker gebruiken, niet alleen - omdat je maar ��n keer wil tikken, maar ook omdat dat stuk het - doet en je bij overtikken fouten kunt maken. - Wat is nu het verschil tussen FUNCTION en PROCEDURE? Het - verschil zit 'm in de uitkomst. FUNCTION heeft een uitkomst, - PROCEDURE niet. Een heel eenvoudige FUNCTION ziet er als volgt - uit: - - FUNCTION Optel(Getal1:integer;Getal2:integer):integer; - BEGIN (* Optel *) - Optel := Getal1 + Getal2; - END; (* Optel *) - - Bovenstaande funktie is dus niets. Je zou hem nooit gebruiken - in een programma, omdat optellen al standaard aanwezig is. Wel - zou je een funktie schrijven om machten te berekenen, omdat - dat niet standaard in PASCAL aanwezig is. Het voorbeeld geeft - wel duidelijk de struktuur van een funktie weer. - Als eerste staat het gereserveerde woord FUNCTION, waarna de - naam van de funktie volgt (let op; gebruik hiervoor geen - gereserveerde woorden!). Tussen haakjes volgen de variabelen - die je nodig denkt te hebben in de funktie tesamen met hun - type (dit stuk is niet verplicht, omdat je niet altijd - variabelen nodig hebt, denk hierbij aan een random funktie). - Als laatste volgt er nog het type van de uitkomst van de - funktie. - - Na deze eerste regel volgt de body van de functie, die - overigens precies gelijk is aan de body van een programma - (ook hier kun je variabelen declareren en andere funkties of - procedures maken). In het code gedeelte is slechts een ding - verplicht en dat is het toekennen van een waarde aan de - funktie (in het voorbeeld "Optel := Getal1 + Getal2"). Doe - je dit niet, dan krijg je gegarandeerd een foutmelding. - Een klasieke fout is overigens het volgende: - - Optel := 0; - FOR Teller := 1 TO 10 DO - Optel := Optel + Getal[Teller]; - - Hiermee zou je een ARRAY kunnen optellen (denk je), maar het - is verboden om de naam van de funktie (Optel) rechts van het - toekenningsteken te plaatsen en dus werkt het niet. Om het wel - aan de praat te krijgen zul je een variabele "Som" moeten - declareren en het volgende moeten doen: - - Som := 0; - FOR Teller := 1 TO 10 DO - Som := Som + Getal[Teller]; - Optel := Som; - - Zo, nu is de uitleg van een procedure een makkie (dus niet). - Eerst een voorbeeld: - - PROCEDURE Uitkomst(Getal:integer); - - BEGIN (* Uitkomst *) - Writeln('De uitkomst is : ',Uitkomst); - END; (* Uitkomst *) - - Alweer zo'n gemakkelijk voorbeeldje (anders begint Koen te - klagen dat 'ie 't nie begrijp, eikel!).(NvdR: leer jij maar - eens een tekstroutine programmeren!) Je ziet dat de struktuur - nagenoeg gelijk is. - Een procedure heeft geen uitkomst en dat blijkt uit de eerste - regel (heading). Verder mag de procedure geen waarde krijgen - (Uitkomst := 10 is dus uit den boze). Voor de rest is alles - gelijk (er mogen dus ook variabelen gedeclareerd en funkties - of procedures gemaakt worden). - - Je weet nu bijna alles van funkties en procedures, ik moet - alleen nog parameter variabelen uitleggen. Bij een funktie of - procedure geef je gewoonlijk ��n of meer variabelen mee, - alleen, je geeft ze niet mee, je copieert ze. Wat ik bedoel - is, dat de waarde die een variable bezit bij aanroep van de - funktie of procedure, wordt gecopieerd. Aanchouw het volgende - voorbeeld: - - FUNCTION T1(Getal1:integer;Getal2:integer):integer; - - BEGIN (* T1 *) - T1 := Getal1 + Getal2; - Getal1 := Getal1 * 2; - END; (* T1 *) - - En vervolgens in het hoofdprogramma de volgende opdrachten: - - A := 10; - B := 20; - Iets := T1(A,B); - - Deze funktie heeft value parameters, wat betekent dat bij de - aanroep wordt gekeken wat de waarde van de formele parameters - (A en B) is en die gecopieerd wordt naar de actuele parameters - (Getal1 en Getal2). De uitkomst is (hoe kan het anders) 30. De - vraag is echter, wat wordt A? In dit geval veranderd A NIET (A - blijft 10). De copie (Getal1) verandert, maar de formele - parameter (A) blijft gelijk, er bestaat geen link. Daarom - noemt men dit value parameters ofwel waarde parameters, alleen - de waarde wordt doorgegeven. - De andere variabelen zijn parameter variabelen. Een funktie of - procedure met parameter variabelen ziet er als volgt uit: - - FUNCTION T2(VAR Getal1:integer;Getal2:integer):integer; - - BEGIN (* T2 *) - T2 := Getal1 + Getal2; - Getal1 := Getal1 * 2; - END (* T2 *) - - Herhalen we nu de aanroep, dan veranderd A wel in 20. A wordt - nu namelijk als referentie meegegeven. Alle bewerkingen op - Getal2 vinden nu rechtstreeks plaats op A. - - Zo, dat was alles wat ik over funkties en procedures kwijt - wilde. Als oefening deze keer kun je alle voorgaande - oefeningen opnieuw doen, alleen met dit verschil dat je in - het hoofdprogramma alleen maar aanroepen doet naar funkties - of procedures. Oh ja, natuurlijk niet maar een procedure - waarin het hele hoofdprogramma gecopieerd wordt (dan heeft - het oefenen nog geen nut). Oefen trouwens ook lekker veel - met het verschil tussen parameter en value parameters. - - Groetjes, - - Jeroen 'KUBIE' Smael - - C YA @!! - diff --git a/Future Disk/15/Data compressie.md b/Future Disk/15/Data compressie.md deleted file mode 100644 index a8d3e06..0000000 --- a/Future Disk/15/Data compressie.md +++ /dev/null @@ -1,103 +0,0 @@ - Data Compressie - - ���� De machinetaal-cursus is naar mijn idee be�indigd - ���� en daarom sluit ik dat dossier en begin met een - ���� cursus. Je denkt misschien:"Hee, die titel heb ik al - ���� eens in de MCCM zien verschijnen??? Schreven Falco - en Ivo daar niet pagina's over vol ???" - - Inderdaad Ivo en Falco schreven er pagina's over vol, maar - lieten je vaak zitten met aanwijzingen hoe het moest en - bespraken maar twee methoden van compressie. In deze cursus - wil ik er een stuk dieper op ingaan dan Falco en Ivo en - lever ik kant en klare PD crunch-routines af, om in je eigen - programma's te gebruiken. Maar laten we eerst het nut van - datacompressie eens bespreken. - - Het nut van datacompressie is, zoals de naam al zegt, het - samenpakken van de orginele data tot een kleiner geheel. Ook - de mogelijkheid om vele files in 1 file samen te pakken, - maakt datacompressie een fijn hulpmiddel om �n ruimte te - besparen, �n overzicht te houden. - - Datacompressie deed zijn intrede rond de tijd van de eerste - harddisks. Plotseling hadden gebruikers 5 MB aan - opslagruimte i.p.v. de 360 KB op een diskette of nog minder - op een cassette. De gebruikers wilden deze opslagruimte zo - efficient mogelijk gebruiken om er zoveel mogelijk - programma's op te zetten. Ook hadden ze voor de uitwisseling - data op de "gewone" diskdrives liefst zo weinig mogelijk - diskettes nodig. Als ze een programma van 5 MB hadden en een - medegebruiker wilde dat programma ook graag hebben (illegale - kopietjes draaien!) wilde men natuurlijk niet met (1 MB/360 - KB) 3 diskettes rond gaan lopen (dan is de pakkans immers - groter) plus dat de man dan zo'n 30 � 40 files zo competent - mogelijk over de diskettes zou moeten verdelen om niet met - nog meer disks over straat te moeten. Daarom werden er - verscheidene compressie methoden uitgedacht door wiskundigen - en informatici om zo compact mogelijk data op te slaan. - - De deskundigen kwamen tot de conclusie dat er in een - data-reeks altijd patronen of repetities van data-elementen - zaten. Deze ontdekking resulteerde in twee methoden van - datacompressie: - - - Het tellen van gelijke opeenvolgende data-elementen en - deze opslaan als data-element + aantal keren opelkaar - volgend voorkomen. - - - Het zoeken naar patronen in de data en deze m.b.v. codes - opslaan. - - De eerste compressie methode heeft het grote nadeel in - bijvoorbeeld tekstfiles. Als er weinig dezelfde elementen - achterelkaar voorkomen, zou het kunnen dat de compressie - zelfs negatief zou gaan werken. Immers, als men aan de - standaard opslag vasthoudt, zou je elk data element opslaan - als: "DATA-ELEMENT + aantal keer opeenvolgend voorkomen" - je dubbel zoveel of meer ruimte nodig had dan het orgineel. - De tweede compressie methode heeft het nadeel dat de - (basis)patronen ongecodeerd moeten worden opgeslagen. - - Het ligt aan de orginele data welke compressie methode het - beste werkt. Een klein voorbeeldje: - - Stel je hebt een leeg SCREEN 8 plaatje. Dit plaatje neemt - (256*212) 54272 bytes aan opslag-ruimte in. Laten we er nu - de eerste compressie methode op los, dan zal het plaatje nog - maar 3 bytes innemen, namelijk "DATA-ELEMENT (0) + aantal - keer opeenvolgend voorkomen (54272)". Dit is een compressie - van 0.00552 % !!!!! - Zou je nu de andere compressie methode erop los laten, dan - zou je (afhankelijk van de patroon zoek methode) altijd een - grotere opslag krijgen dan de 3 bytes van de andere methode. - - Maar.....neem deze tekstfile eens als voorbeeld. Als we hier - de eerste methode op zouden loslaten zouden we een enorme - negatieve compressie krijgen. De opeenvolging van dezelfde - data-elementen (de letters dus) is extreem zeldzaam. Het - woord "Boemel", normaal 6 bytes, zou worden opgeslagen - als: "B"(1)+"o"(1)+"e"(1)"+"m"(1)+"e"(1)+"l"(1) = 12 bytes. - Dit is een compressie van 200%, zeer negatief dus ! - Met de andere methode zou de computer kunnen vinden dat de - "e" als patroon 2x voorkomt en dus een kleinere bitlengte - moet krijgen dan de andere elementen (Huffman-principe). De - compressie zou nog steeds niet groot zijn, maar altijd nog - niet negatief. Alleen de opslag van de patroontabel zou de - uiteindelijke compressiefile weer groter kunnen maken dan - het orgineel. - - Overigens heeft datacompressie natuurlijk geen zin op een - reeks als "ABCDEFGHIJKLMNOP". Hierin is zelfs door mensen - geen patroon of opeenvolging in te vinden dus heeft het meer - zin om deze data "gewoon" op te slaan. De beste compressie - methode zou natuurlijk moeten kijken of de compressie wel - zin heeft, want om negatieve compressie staat niemand te - springen. - - Zo, dit is ongeveer de inleiding en de benodigde achtergrond - kennis om deze cursus te begrijpen en de eruitvoorkomende - programma's zelf te kunnen maken en nieuwe compressiemetho- - den te programmeren. - - Jan-Willem van Helden diff --git a/Future Disk/15/Pascal 5.md b/Future Disk/15/Pascal 5.md deleted file mode 100644 index caf0759..0000000 --- a/Future Disk/15/Pascal 5.md +++ /dev/null @@ -1,85 +0,0 @@ - - PASCAL 5 - ======== - - ���� Alweer deel 5 van deze cursus! Wat gaat de tijd toch - ���� snel. Deze keer een kleine cursus, omdat het over - ���� een gemakkelijk onderwerp handeld. Deze cursus - ���� behandeld namelijk het maken van eigen types. - - Bij het declareren van een variabele konden we tot nog toe - alleen maar kiezen uit de standaard type's (integer, real, - boolean, etc.). In PASCAL is het echter ook mogelijk om je - eigen type's te maken en wel als volgt: - - TYPE - OpsomType = {Item1,Item2,Item3}; - SubrangeType = 1..10; - ArrayType = ARRAY[1..10] OF AnderType; - - Je kunt dus een opsommingstype maken bijvoorbeeld: - - DagenVanDeWeek = {Maandag,Dindag,Woensdag,Donderdag,Vrijdag, - Zaterdag,Zondag} - - Of een subrangetype (van elk ander type). Bijvoorbeeld: - - DagenVanDeMaand = 1..31 (* integers dus *) - - Of een ARRAY type. Bijvoorbeeld: - - WekenVanEenJaar = ARRAY[1..52] OF DagenVanDeWeek - - Vervolgens kun je de types gebruiken, maar let wel goed op met - toekenningen e.d. Neem bijvoorbeeld het volgende: - - VAR - Dag : DagenVanDeWeek; - - Dan mag - - Dag:=Maandag; - - Maar niet - - Write("Geef dag : "); - Readln(Dag); - - De type's verschillen immers. Bij Readln lees je een integer, - real of string, maar niet een DagenVanDeWeek. - - Wat ook niet kan is - - Dag:=Maandag; - Writeln("Het is vandaag ",Dag); - - En wel om dezelde reden als bij Readln. Wat wel kan is - - Dag:=Maandag; - CASE Dag OF - Maandag : Write("Maandag"); - Dinsdag : write("Dinsdag"); - . - . - . - - Experimenteer maar eens een beetje met het cre�ren van eigen - type's en je zult zien dat dit heel handig kan zijn. - - Een functie die een beetje met deze type declaratie te maken - heeft is de IN functie. Deze werkt als volgt: - - IF Dag IN {Maandag,Dinsdag,Woensdag,Donderdag,Vrijdag} THEN - writeln("Dit is een werkdag"); - - Je kunt dus met IN kijken of de waarde van een variabele in - een gegeven verzameling zit. Die verzameling moet je wel eerst - opsommen, maar dat is een kleine prijs om te betalen tegenover - (in dit geval) 5 IF statements. - - Zo, dit was kort maar krachtig(NvdR: geloof je dat nou - zelf?). - - Jeroen "Ik beloof beterschap" Smael - - C YA @!! diff --git a/Future Disk/15/The 2+ Corner.md b/Future Disk/15/The 2+ Corner.md deleted file mode 100644 index e801201..0000000 --- a/Future Disk/15/The 2+ Corner.md +++ /dev/null @@ -1,118 +0,0 @@ - The 2+ Corner - - - Veel mensen weten nog steeds niet wat de MSX2+ allemaal - extra biedt t.o.v. een MSX2. Natuurlijk iedereen weet dat - de 2+ veel meer kleuren heeft dan een MSX2 en dat hij een - hardware scroll heeft, maar er zijn wel wat meer dingen - verandert... - - Kun-Basic - - Een 2+ heeft een ingebouwde Kun-Basic die door middel - van _BC uit basic opgeroepen kan worden. Vooral als - je zelf vaak in basic programmeert kan dit heel - handig zijn. - - Kanji-basic - - Hoewel Kanji-basic op het eerste gezicht een beetje - nuttleloos lijkt is het soms toch best wel handig b.v. je - wilt een keer een file menu maken in screen7 in gewoon - basic moet je dan een best ingewikkelt programma maken om - de files op het scherm te krijgen in Kanji-basic zet je - gewoon FILES in je programma en... HOP; je hebt de files in - screen 7. Ook kan je in elk scherm de commando's PRINT en - LOCATE gebruiken dus geen gemier met OPEN"grp:" FOR OUPUT - AS #1. - Simpel toch. (kanji-basic zit ook in de dos2.XX cartridge) - - Hardware scroll - - E�n van de beste uitbreidingen op een 2+ is wel het scroll - commando. Dankzij die hardware Scroll kan je simpel, �n elk - scherm in elke richting scrollen. - - Commando functie - - Met R#46 kan je commando's geven aan de VDP zoals - copy, line, point,ect,ect maar die commando's werken echter - op een MSX-2 alleen in de schermen 5 to 8. Op een 2+ kan - dit in elk scherm als je de commando functie aan zet - in R#25 (bit 6). - - Wait functie - - In R#25(NvdR: in Basic is dit VDP(26)) kan je ook de wait - functie aan zetten (bit2). - Dat zorgt er voor dat wanneer de CPU naar het Vram schrijft - alle poorten van de V9958 in de wacht mode worden gezet. - Hierdoor wordt de schrijftijd van de CPU naar het vram - verkleind. - - Reset - - Na een reset wordt er gezorgt dat gekraakte Rom's ed niet - weer opstarten, dit is vooral handig voor de Sony mensen - onder ons die soms wel ��n minuut moeten wachten voordat - een spel uit het geheugen is. Het geheugen wordt niet - gewist, want dan zou een reset bestendige ramdisk na een - reset wel weg zijn. - - Opstarten - - Bij het opstarten van de 2+ wordt al het geheugen bij - elkaar opgeteld, dit in tegen stelling tot een MSX2. - Een MSX2 print gewoon op het scherm wat er standaard in zit - en bij sommige MSX computers geeft hij bij het opstarten - helemaal niet aan hoeveel ram er aanwezig is. - - Nieuwe schermen - - Ja, hier valt weinig over te zeggen alleen dat digi's gewoon - veel mooier op screen 12 zijn dan in screen 8. - Het leuke van screen 11 is dat je daar naast de 12499 YJK - kleuren ook nog 16 RGB kleuren hebt waarmee je de color - spil weg kan werken. - By the Way het enige verschil tussen screen 10 en 11 is hoe - basic 3.0 er mee omgaat in ML is er geen verschil. - Daar is gewoon geen screen 10. - (iemand enig idee waarom screen 9 niet bestaat?) - (NVDR: SCREEN 9 werd opgekocht door een Koreaans bedrijf dat - SCREEN 9 zo gebouwd heeft dat de Koreaanse karakterset erin - gebruikt kan worden! SCREEN 9 is dus alleen ingebouwd in - alle Koreaanse MSX-2's!) - - Wat mij opvalt is dat er veel meer 2+ computers zijn dan - sommige mensen denken. Als je aan sommige programmeurs - vraagt waarom ze niets voor de 2+ maken dan zeggen ze dat - de 2+ niet veel extra's biedt, maar daar ben ik het niet mee - eens... - Kijk nou eens naar het spel LAYDOCK 2 Last Attack - Heeft iemand zo'n mooi spel op de MSX-2 gezien? Omdat de - MSX-2 niet goed kan horizontaal scrollen (NVDR: LEES OMDAT - JE MET DE V9938 NIET...) in de schermen 5 to 8, zijn - de spellen die horizontaal scrollen meestal in screen 4 - gemaakt. Zie bijvoorbeeld Hydefoss, Psycho World, Space - Manbow, en zo kan ik nog wel even doorgaan. De graph-x in - die spellen hebben er dan ook aan te lijden. Op een 2+ - zouden die spellen veel mooier kunnen... - - In de MCCM stond bij de recensie van Mega doom dat je - moest oppassen dat dit spel 128KB nodig heeft. Wie heeft er - tegenwoordig nog 64KB? Misschien is er nog 1 persoon in - Nederland die een MSX2+ met 64KB heeft, maar dat lijkt me - wel heel erg onwaarschijnlijk. Met 64KB kan je bijna geen - software draaien... - - Als je een GIF freak en je hebt een MSX-2 dan zou ik je - computer maar laten ombouwen naar een 2+, want in screen 12 - zijn Gif plaatjes gewoon zo als ze moeten wezen en niet met - allemaal vieze kleuren zoals in screen 8. - - Marcel Otten - - PS OP FUTUREDISK #16 STAAN ENKELE KLEINE PROGRAMMAATJES VAN - MARCEL, GENAAMD "SCROLL.LDR" en "4096.LDR" - DEZE PROGRAMMA'S WERKEN NATUURLIJK ALLEEN OP MSX-2+ of - TURBO-R. LET OP; SCROLL.LDR werkt ALLEEN met MUIS! diff --git a/Future Disk/17/Basic Cursus 6.md b/Future Disk/17/Basic Cursus 6.md deleted file mode 100644 index e4919cf..0000000 --- a/Future Disk/17/Basic Cursus 6.md +++ /dev/null @@ -1,117 +0,0 @@ - BASIC Cursus?! - -���� Okay mensen. Tom ligt er uit (Yes!) en Tobias herstart -���� bij deze dus de BASIC cursus. Natuurlijk kan Tobias niet -���� verder gaan waar Tom gebleven was. In de eerste plaats -���� niet omdat Tom een eikel is en in de tweede plaats - omdat Tobias' aanpak compleet anders is. Wij bedanken U -voor Uw begrip. Het woord is aan Tobias... - - BASIC CURSUS (6) - - ���� - ���� - ���� - ���� - - SHIFT en ander gekakel... - - - Toen ik een klein jongetje was had ik maar ��n droom. - (Waag 't niet Koen!) Ik wou zo graag de Shift toets en dat - soort onzin toetsen uitlezen(NvdR: and that's your dream?). - Maar ja, met inkey$ ging dat zo moeilijk. Toen ging ons - Tobiasje naar een oude wijze Guru. Roman van der Meulen. - Roman was alleen een beetje lui en riep alleen 't woord - "Toetsen bord buffer" uit om vervolgens weer te gaan slapen. - Toen ging ons Tobiasje maar naar een andere wijze Guru: - Jan van Valburg. Maar Jan was nogal druk met allerlei - vunzige bezigheden achter z'n computer (WIDEOPEN.GIF) en kon - ons Tobiasje ook niet helpen. Ten einde raad ging ons - Tobiasje huilend terug naar huis, nog steeds niet wetend hoe - hij de Shift toets moest uitlezen. Toen kwam Tobiasje een - minstens 50 kilo te zware, wild behaarde, en veel te naive - hippie tegen: Wammes Witkop. Wammes had een eigen blad voor - MSX en kende dus heel veel mensen. Ook kende hij iemand die - wel graag toetsen uitlas: Hayo Rubingh(NvdR: dat was vroeger - ook echt mijn hobby!). Hayo was echter druk bezig andere - muziek-programma's af te zeiken en verwees Tobiasje door - naar Albert Huitsing die eigenlijk 't hele MIDI gedeelte - heeft gedaan waar Hayo altijd de eer van opstreek/opstrijkt. - Albert kon Tobiasje wel helpen en legde het volgende uit: - - OK lieden, het hele gezeik over de interrupt en al dat geemmer - over hoe al die data in de toetsen bordbuffer komt ga ik - niet weer helemaal uitleggen. Als je dat niet weet zoek je - maar de dichtst bijzijnde brug op. KEYBUF ga ik niet - behandelen omdat die niet zo gek interressant is. NEWKEY - echter is veel interressanter. NEWKEY loopt van &HFBE5 tot - &HFBEF en is dus 11 bytes groot. Wat precies klopt gezien - 't feit dat er 11 rijen zijn. NEWKEY kan vanuit BASIC gewoon - met een PEEKje worden uitgelezen alleen dan is 't wel - belangrijk om de matrix van zowel de Jappen als de - internationalen te weten. Die rommel die toen door PHILIPS - en SONY is gemaakt wilt nog wel eens moeilijk doen, maar - voor zover ik weet klopt die int. matrix wel redelijk. Eerst - de beide matrixen: - - Toetsenbord matrix Europeaan: - - Adres Rij B i t n u m m e r - 7 6 5 4 3 2 1 0 - - &HFBE5 0 7 6 5 4 3 2 1 0 - &HFBE6 1 ; ] [ \ = � 9 8 - &HFBE7 2 B A ACC / . , ` ' - &HFBE8 3 J I H G F E D C - &HFBE9 4 R Q P O N M L K - &HFBEA 5 Z Y X W V U T S - &HFBEB 6 F-3 F-2 F-1 CODE CAPS GRPH CTRL SHFT - &HFBEC 7 RET SEL BS STOP TAB ESC F-5 F-4 - &HFBED 8 RGHT DOWN UP LEFT DEL INS HOME SPC - &HFBEE 9 4 3 2 1 0 not not not numeriek - &HFBEF A . , � 9 8 7 6 5 eiland - - Toetsenbord matrix Japanner: - - Adres Rij B i t n u m m e r - 7 6 5 4 3 2 1 0 - - &HFBE5 0 7 6 5 4 3 2 1 0 - &HFBE6 1 ; [ @ Yen ^ � 9 8 - &HFBE7 2 B A _ / . , ] : - &HFBE8 3 J I H G F E D C - &HFBE9 4 R Q P O N M L K - &HFBEA 5 Z Y X W V U T S - &HFBEB 6 F-3 F-2 F-1 KANA CAPS GRPH CTRL SHFT - &HFBEC 7 RET SEL BS STOP TAB ESC F-5 F-4 - &HFBED 8 RGHT DOWN UP LEFT DEL INS HOME SPC - &HFBEE 9 4 3 2 1 0 not not not numeriek - &HFBEF A . , � 9 8 7 6 5 eiland - - - Nu je beide matrixen hebt kun je al aan de slag. Met een - ordinairde PEEK valt 't gewenste adres uit te lezen. Is een - bit 0 dan is de betreffende toets ingedrukt. Om dus te kijken - of de shift toets is ingedrukt, zoals kleine Tobiasje dat - wilde, maken we dus 't volgende listinkje: - - 10 IF PEEK(&HFBEB)<>&B11111111 THEN PRINT"J" ELSE PRINT "N" - - Maar een ieder kan zien dat dit niet echt netjes is, wordt - namelijk F-1 ingedrukt, verschijnt er ook J in beeld. F-1 - staat immers ook in rij 6. Maar hoe test je nu op alleen - bit 0 van rij 6? Simpel, 't zooitje ANDen. Dan krijg je dus: - - 10 IF (PEEK(&HFBEB)AND&B00000001)=0 THEN PRINT"J" - - Natuurlijk mogen de rijen en kolomen verschillen maar dit is - wel zo'n beetje hoe je 't best 't keyboard kan uitlezen. Dit - is overigens ook handig als er iets ingevoerd moet worden maar - je dit niet aan de basic interpreter wil overlaten. Ook voor - pull-down menutjes -die vaak met een non�active toets - geactiveerd worden- is dit handig. Well folks, that's about - it for today... next time I'll errr... well I don't know, but - it'll be more usefull than this shit.... bye - - Tobias 'fushigi' Keizer diff --git a/Future Disk/17/Data compressie 2.md b/Future Disk/17/Data compressie 2.md deleted file mode 100644 index cc66702..0000000 --- a/Future Disk/17/Data compressie 2.md +++ /dev/null @@ -1,141 +0,0 @@ ----- Data Compressie (2) ---- - - ���� Er wordt dit keer begonnen met het echtere werk. - ���� De aflevering van de vorige keer was een inleiding - ���� op hetgene wat ik in de volgende cursi zal behandelen. - ���� - - - Allereerst beginnen we nog eens met de grondregel van - datacompressie: we willen een groot geheel als een kleiner - geheel opslaan. - - Om dit te doen kennen we verschillende methoden. Dit keer - beginnen we met de makkelijkste methode: - - ---- RUNLENGTH ---- - - Falco en Ivo Wubbels schreven er al over en plaatsten een - source in de MCCM die wel erg 'basic' was. Daarom zullen we - proberen een zo groot mogelijke compressie te behalen - met behulp van Runlength-encoding. Maar eerst wat meer over - Runlength. - ----- Wat is RUNLENGTH ??? ---- - - Runlength is een compressie-methode die ervan uitgaat dat er - lange reeksen van gelijke data-elementen in een bestand - voorkomen. Deze reeksen verkleint runlength door de - achtereenvolgende gelijke data-elementen te tellen en ze als - [Waarde] + [Aantal keer opeenvolgend] op te slaan. - ----- RUNLENGTH ALGORITHME ---- - - Om dit te verduidelijken, kijken we eens naar het volgende - voorbeeld, dat de algorithme voor het opslaan van runlength - voorstelt: - - [0] TELLER = 1; - [1] LEES DATAELEMENT; - [2] {X} <- VOLGENDE DATAELEMENT IN BESTAND; - [3] IS DATAELEMENT GELIJK {X} ?; - - (JA: VERHOOG TELLER; - GA NAAR [2]; - ) - (NEE: STUUR DE WAARDE VAN HET DATAELEMENT + AANTAL - KEER VOORKOMEN NAAR DE CODE; - GA NAAR [0]; - ) - - ---- SOURCE LISTING ---- - - Met deze pseudo-code kunnen we makkelijk een assembly- - listing maken: - - ; RUNLENGTH - ; (c) 1994 FutureDisk - - DATA: EQU #A000 - CODE: EQU #B000 - - ORG #C000 - - LD C,1 ;C = teller - - LD HL,DATA ;orginele data - LD DE,CODE ;output opslag - OPNIEW: - LD A,(HL) ;lees eerste data- - ;element - LOOP: - INC HL - CP (HL) ;vergelijk volgende - ;element - JP NZ,NGELYK - INC C ;gelijk: verhoog de - ;teller - JP LOOP ;onderzoek volgende - ;element - NGELYK: - LD (DE),A ;sla het data-element - ;op - INC DE - LD A,C - LD (DE),A ;sla de teller op - INC DE - LD C,1 ;reset de teller - JP OPNIEW ;neem ongelijke - ;element als nieuw - ;data-element. - END - - - Zoals je al ziet gaat deze routine eeuwig door. Dit is - natuurlijk makkelijk te verhelpen door bij elke verhoging - van HL te bekijken of deze is aangekomen bij het einde van - de te comprimeren reeks. - ----- UITGEWERKT VOORBEELD ---- - - Nu de algoritme en een kleine source-listing gemaakt zijn - gaan we eens kijken naar een klein getallen voorbeeldje: - Onze originele data ziet er zo uit: 'AAABBACCCDDDD' - Gaan we stap voor stap door de algoritme. Als eerste - data-element nemen we de A. We vergelijken die met het - volgende element. Alweer een A --> we verhogen de teller en - bekijken het volgende element, weer A --> teller+1 en bekijk - volgende element, een B. We slaan nu het data-element A op - en plaatsen daarachter de teller. De code is nu 'A3'. We - nemen nu de B als data-element, zetten de teller weer op 1 en - vergelijken B met het volgende element --> weer een B, - vergelijken met het volgende element --> een A. We slaan B op - en daarachter de teller. De code is nu 'A3B2'. We zetten de - teller op 1, nemen A als data-element en vergelijken met de - volgende --> een C. We slaan de A op, daarachter de teller, - code is 'A3B2A1', zetten teller op 1 en nemen C als - data-element. C komt 3 keer voor en D nog 4 maal, dus de - code wordt 'A3B2A1C3D4'. Je ziet dat er een kleine - compressie is behaald. Toch komt in dit voorbeeld ook al 1 - van de nadelen van runlength boven water, namelijk het - opslaan van de A tussen de B en de C. Deze A komt maar 1 - keer in het orgineel voor, maar neemt twee elementen in in - de code, namelijk A en 1. Op zich hoeft dit nog geen - probleem te zijn, maar zodra we een bestand krijgen waarin - (bijna) geen opvolging van gelijke elementen zit, zal de - compressie niet goed werken, sterker nog, zal negatief gaan - werken. Het resultaat wordt namelijk groter dan het - orgineel. Gelukkig is hier een, niet zo moeilijke, oplossing - voor te vinden, waardoor runlength toch een redelijke - compressie-methode blijft. De volgende keer gaan we hier - echter verder op in. - - ---- VOLGENDE KEER ---- - - Volgende keer volmaken we dus het runlength-encoden en - behandelen het decoden. Ook maken we dan spelenderwijs een - runlength encoder-decoder om grafische schermen mee te - comprimeren. - - Jan-Willem van Helden - diff --git a/Future Disk/17/Pascal 6.md b/Future Disk/17/Pascal 6.md deleted file mode 100644 index 38ac574..0000000 --- a/Future Disk/17/Pascal 6.md +++ /dev/null @@ -1,245 +0,0 @@ - - PASCAL 6 - ======== - - - ���� Tja, vorige keer was ik er niet helemaal met mijn koppie - ���� bij, want ik heb een deel van wat ik moest vertellen - ���� vergeten(NvdR: de eikel!). Ik heb verteld dat je eigen - ���� types kunt maken, maar ��n van de belangrijkste types ben - ik vergeten. Ik ben namelijk het RECORD en de string - vergeten. Hierbij dan ook mijn excuses en de aanvullende - informatie. - - TYPE - - Over de string kan ik heel snel zijn. De string is een "PACKED - ARRAY[1..?] of char". Een PACKED ARRAY is een array waarvan de - lengte intern wordt bijgehouden. Iets wat bij een string - noodzakelijk is, anders geven programma's als: - - PROGRAM StringVoorbeeld; - - TYPE - Woord = PACKED ARRAY[1..10] OF char; - - VAR - A : Woord; - B : Woord; - - BEGIN (* StringVoorbeeld *) - A:='hallo'; - B:=A; - Writeln(A); - Writeln(B); - END. (* StringVoorbeeld *) - - Het bovenstaande programma lijkt goed (A:=B mag bij arrays, - zolang de arrays van het zelfde type en even groot zijn), maar - er zal twee keer het woord 'hallo' verschijnen, met daarachter - 5 ongewilde karakters (mocht het zo zijn dat het programma - niet al een foutmelding geeft bij de opdracht A:='hallo', - omdat dat niet voldoet aan de voorwaarde van dezelfde grote). - Bij een PACKED ARRAY zoekt de computer zelf uit hoe groot het - ARRAY is en lost alle genoemde problemen dus op. Bij een - aantal compilers is het mogelijk om een type te gebruiken dat - "string" heet. Genoemd type wordt gebruikt bij TYPE met - "woord = string[10]" of bij VAR met "A : string[10]". - - Dat ik RECORD's vergeten ben is veel erger, omdat daar nou juist - de meeste leuke dingen mee gedaan kunnen worden. Een klein - voorbeeldje: - - PROGRAM RecordVoorbeeld; - - TYPE - datum = RECORD - dag : 1..31; - maand : 1..12; - jaar : 0..5000; - END; - persoonsgegevens = RECORD - naam : string[30]; (* ik maak - gebruik van - het string - type *) - geboortedatum : datum; - END; - - VAR - persoon : persoonsgegevens; - - BEGIN (* RecordVoorbeeld *) - persoon.naam:='Jeroen Smael'; - persoon.geboortedatum.dag:=27; - persoon.geboortedatum.maand:=10; - persoon.geboortedatum.jaar:=1970; - END. (* RecordVoorbeeld *) - - Op deze manier kun je dus hele gegevens "bomen" aanleggen. Bij - de persoonsgegevens kun je ook nog het adres, de geboortestad, - etc., etc. toevoegen. Alles wat je maar wilt. Zoals je ziet - moet je wel, om bij de velden te komen een punt gebruiken. - Deze punt is vergelijkbaar met de \ van DOS (het scheidings- - teken van subdirectory's). Tevens zie je dat ik pas jarig ben - geweest, maar dat terzijde(NvdR: so?). - - Met genoemde velden zijn verder natuurlijk wel alle - bewerkingen mogelijk, zo zou de opdracht: - "persoon.geboortejaar:=persoon.geboortejaar+1" een geldige - opdracht zijn. - - Een hele bruikbare "opdracht" bij records is de CASE opdracht. - Deze maakt het mogelijk om een of meerdere veldnamen weg te - laten. Met gebruikmaking van de CASE opdracht zou het vorige - (hoofd)programma er als volgt hebben uitgezien: - - BEGIN (* RecordVoorbeeld *) - CASE Persoon OF - naam:='Jeroen Smael'; - geboortedatum.dag:=27; - geboortedatum.maand:=10; - geboortedatum.jaar:=1970; - END; - END. (* RecordVoorbeeld *) - - Hetzelfde (de CASE) kunnen we natuurlijk ook toepassen bij de - geboortedatum en dan ziet het (hoofd)programma er als volgt - uit: - - BEGIN (* RecordVoorbeeld *) - CASE Persoon OF - naam:='Jeroen Smael'; - CASE geboortedatum OF - dag:=27; - maand:=10; - jaar:=1970; - END; - END; - END. (* RecordVoorbeeld *) - - Zoals te zien spaart dit een heleboel tikken. Let er - natuurlijk wel op dat de CASE afgesloten wordt door een END - (anders krijg je een compiler fout). - - Files - - Het zou uiteraard ook leuk zijn als we met PASCAL toegang - zouden hebben tot de diskette. Gelukkig hebben de makers - daaraan gedacht en kan dat. Voor de beeldvorming zal ik - uitleggen hoe PASCAL een file "ziet". - - Een file is in PASCAL een lange keten gegevens. De gegevens - zitten (en zullen ten eeuwige dagen blijven zitten) in de - volgorde waarin ze zijn weggeschreven. Bij het werken met een - file schuift er een "window" over de file, waardoor altijd - maar ��n gegeven per keer "zichtbaar" is. Het genoemde window - heeft trouwens de onprettige eigenschap dat het alleen maar - vooruit kan schuiven. Ophalen en wegschrijven van waardes - gebeurt via het window. Het window is te bereiken met "File^" - (waar File de naam van de filevariabele is). Ik zal nu wat - opdrachten bespreken die mogelijk zijn met files, waarna nog - een voorbeeld programma volgt. Opdrachten zijn: - - RESET(File) - Opent een file zodat er in gelezen kan worden (zet het - window aan het begin van de file). - REWRITE(File) - Opent de file en maakt hem geschikt om in te schrijven - (file is nu leeg, ook al was hij dat niet!!). - GET(File) - Schuift het window een plaats op (de nieuwe waarde kan met - "Waarde:=File^" opgevraagd worden). - PUT(File) - Zet de waarde van het window in de file en schuift het - window een plaats op (de window waarde kan veranderd worden - met "File^:=Waarde"). - READ(File,Waarde) - Leest uit de file en plaats de gelezen waarde in "Waarde" - (geen geklooi meer met het window, hier gebeurt dat - allemaal automatisch). - READLN(File,Waarde) - Idem als READ, maar leest tevens tot het einde van de regel - (wordt gebruikt bij tekstfiles). - WRITE(File,Waarde) - Schrijft de waarde van "Waarde" in de file en schuift het - window door (ook hier geen geklooi meer met het window). - WRITELN(File,Waarde) - Idem als WRITE, maar plaatst tevens een EOLN (End OF LiNe) - teken in de file (wederom bij tekstfiles). - EOF(File) - Geeft de waarde TRUE als het einde van de file bereikt is - (EOF = End Of File). - EOLN(File) - Geeft de waarde TRUE als het einde van de regel bereikt is - (EOLN = End Of LiNe). - - Officieel zijn genoemde opdrachten alle opdrachten voor files, - maar de meeste compilers hebben nog twee extra opdrachten en - dat zijn: - - ASSIGN(File,"FileNaam") - Dit koppelt de "File" aan de "FileNaam". M.a.w. Als ik iets - in de file schrijf, dan komt dit op de schijf in de file - "FileNaam" te staan. Volgens de regels van PASCAL is dit - niet nodig, omdat de fysieke file (de file op schijf) - dezelfde naam krijgt als de variabele "File" heeft. Veel - compilers hebben echter een ASSIGN opdracht nodig, anders - gebeurt er niets (vaak niet eens een foutmelding en al - helemaal geen file). - CLOSE(File) - Dit moge wel duidelijk zijn. Hier wordt de file gesloten. - Deze opdracht zorgt ervoor dat de file ook voor DOS - gesloten wordt, zodat er niet een ge-opende file achter- - blijft als het programma stopt. Deze opdracht moet dus - alleen op het einde van het programma staan. Ook deze - opdracht is geen standaard, maar moet ook bij de meeste - compilers worden toegevoegd voor een goede werking. - - Zo, en dan nu een voorbeeldje: - - PROGRAM FileVoorbeeld; - - TYPE - FileType = FILE OF integer; (* FILE OF AnyType is - mogelijk *) - - VAR - FileVar : FileType; - Teller : integer; - - BEGIN (* FileVoorbeeld *) - ASSIGN(FileVar,"testfile.dat"); (* voor de zekerheid *) - REWRITE(FileVar); (* ik wil er iets - inschrijven *) - FOR Teller:=1 TO 5000 DO - Write(FileVar,Teller); (* dat doe ik hier *) - FOR Teller:=5000 DOWNTO 1 DO - Write(FileVar,Teller); (* en hier ook *) - RESET(FileVar); (* nu wil ik lezen uit - de file *) - WHILE NOT EOF(FileVar) DO - BEGIN - Read(FileVar,Teller); (* hier noem ik - expliciet de file *) - Write(Teller); (* hier niet, dus gaat - de output naar het - standaard uitvoerap- - paraat en dat is het - beeldscherm *) - END; - CLOSE(FileVar); (* voor de zekerheid *) - END. (* FileVoorbeeld *) - - Dit voorbeeld zou een heleboel duidelijk moeten maken. Alles - wat je nu nog moet doen is verder experimenteren. Probeer eens - een tekstfile te lezen en/of schrijven, dan kun je zien wat - EOLN precies doet. - De opdrachten GET en PUT worden weinig gebruikt, maar je kunt - eens kijken hoe ze precies werken (goed voor de beeldvorming). - - Zo, dat was het dan alweer voor deze keer. Groetjes van, - - Jeroen 'ik ben nog lang niet aan mijn EOF' Smael - - C YA @!! diff --git a/Future Disk/18/Data compressie 3.md b/Future Disk/18/Data compressie 3.md deleted file mode 100644 index 31e8245..0000000 --- a/Future Disk/18/Data compressie 3.md +++ /dev/null @@ -1,316 +0,0 @@ ----- Data Compressie (3) ---- - - - ���� Zoals vorige keer beloofd, ga ik verder met het vol- - ���� maken van de RUNLENGTH-methode. Of we aan het voor- - ���� beeld toekomen hangt af van mijn beschikbare tijd en - ���� de beschikbare diskruimte (NvdR: Ja, schuif maar af!) - - Laten we nog eens het voorbeeld van vorige keer herhalen: - We hadden de data 'AAABBACCCDDDD'. Na de stappen van het - RUNLENGTH-algoritme te hebben gevolgd kwamen we tot de - conclusie dat de gecrunchte data 'A3B2A1C3D4' zou worden. - Als je het allemaal niet meer helemaal weet, lees het dan - nog eens na op FD #17. - - Zoals vorige keer al opgemerkt is het element 'A1' storend. - We slaan immers dit als 2 bytes op (een byte voor 'A' en een - byte voor het aantal keer dat ie voorkomt '1'), terwijl er - in het orgineel maar 1 byte voor die 'A' nodig was. - Als dit maar weinig voorkomt treedt er natuurlijk geen - probleem op, maar als dit heel vaak gebeurt, is je - compressie zeer inefficient. Zo is het mogelijk om een 2 - keer zo grote file als output te krijgen. - - Om dit op te lossen kunnen we een extra byte bij de - crunch-data nemen. - -Eeuh, wat ? - - Nou kijk; we gaan nu in ons algoritme opnemen dat een byte - aangeeft of er crunch-data achterstaan of dat het - data-element gewoon ongecodeerd is opgeslagen. We noemen - deze byte even "CMP-ON" (CoMPression-ON). Voor onze - pseudo-code houdt dat dit in: - - [0] TELLER = 1; - [1] LEES DATAELEMENT; - [2] {X} <- VOLGENDE DATAELEMENT IN BESTAND; - [3] IS DATAELEMENT GELIJK {X} ?; - - (JA: VERHOOG TELLER; - GA NAAR [2]; - ) - (NEE: - [4] IS TELLER > 3 ?; - (JA: STUUR "CMP-ON"-BYTE NAAR DE CODE; - STUUR DE WAARDE VAN HET DATAELEMENT + - AANTAL KEER VOORKOMEN NAAR DE CODE; - GA NAAR [0]; - ) - (NEE: STUUR TELLER * HET DATAELEMENT NAAR DE - CODE; - GA NAAR [0]; - ) - ) - - Zoals je ziet lijkt het geheel nog steeds op het oude - voorbeeld. Opvallend is het toevoegen van een extra routine, - n.l. [4]. Deze routine kijkt of de TELLER groter is dan 3. - -Waarom 3 ?? - - Logisch, laten we even ervan uitgaan dat we het aantal - opslaan in een byte, het aantal in een byte en dat de - "CMP-ON" ook een byte inneemt. Samen maken dit 3 bytes. Als - we nu een data-element hebben dat maar 1 of 2 keer voorkomt, - heeft het natuurlijk weinig zin om dit gecomprimeerd op te - slaan. Dit zou namelijk tot gevolg hebben dat de code 3* zo - groot zou worden als het origineel. Een nog slechtere - compressie dan "normale" RUNLENGHT al zou hebben. Vandaar - deze extra stap [4]. - - Oplettende en zeer intelligente lezers hebben al opgemerkt - dat het programma voor de "CMP-ON" ��n byte gebruikt. Wat - gebeurt er nu als de waarde van het data-element gelijk zou - zijn aan de waarde van "CMP-ON"? Voor zowel het encoden als - decoden zou dit niets uitmaken, als de TELLER > 3 zou zijn. - Dat werkt gewoon. Als de TELLER <=3 zou zijn zou het encoden - ook geen probleem opleveren. Het programma zet gewoon 1 of 2 - (of 3, ligt aan de realisatie van je algoritme) bytes met - de waarde van "CMP-ON" in de code. Echter bij het decoden - de hele heisa fout gaan lopen. Kijken we maar eens wat er - gebeurt: - - Stel onze code is dit: - - [CMP-ON], "A" , "CMP-ON","A","40" - \ \ \ - byte waarde "CMP-ON" \ frequentie - \ - ongecodeerde byte - - Pakken we dat eens uit: Eerst vindt de decoder een byte met - de waarde "CMP-ON". Helaas herkent de decoder deze niet als - zijnde een waarde maar leest nu dat dit betekent dat de - volgende 2 bytes bestaan uit eerst een data-element en - daarna het aantal keer dat dit element voorkomt. De decoder - plaatst dan in het geheugen "CMP-ON" * "A"-tekens, terwijl - bedoeld was om eerst een byte met waarde "CMP-ON", dan een - byte met waarde "A" en dan een reeks van 40 bytes met waarde - "A". De decoder zal dus weinig begrijpen van de data. - -Hoe lossen we dit op??? - - Simpel! In het algoritme moeten we als de TELLER lager is - dan 3 de clausule opnemen dat een byte met de waarde van - "CMP-ON" moet worden opgeslagen alsof de TELLER > 3. In - pseudo code is er dan de aanpassing: - - [1] TELLER = 1; - | | | | | | - [3] IS DATAELEMENT GELIJK {X} ?; - - (JA: VERHOOG TELLER; - GA NAAR [2]; - ) - (NEE: - [4] IS TELLER > 3 ?; - (JA: STUUR "CMP-ON"-BYTE NAAR DE CODE; - STUUR DE WAARDE VAN HET DATAELEMENT + - AANTAL KEER VOORKOMEN NAAR DE CODE; - GA NAAR [0]; - ) - (NEE: - [5] IS DATAELEMENT = "CMP-ON" ?; - (JA: GA NAAR DE AFHANDELING VOOR - TELLER > 3; - ) - (NEE: STUUR TELLER * HET DATAELEMENT - NAAR DE CODE; - GA NAAR [0]; - ) - ) - - - Nu werkt dus het gehele encoden en decoden goed, maar treedt - er nog steeds soms negatieve compressie op. Immers als je - net een aantal keer "CMP-ON" afgewisseld met andere bytes - tegenkomt in je data, dan slaat de encoder als deze - "CMP-ON"'s op als 3 bytes. - -LEES VERDER IN TEKST 2! - - ---- Data Compressie 3-2 ---- - - -....VERVOLG - - Het moge duidelijk zijn dat de waarde "CMP-ON" moet worden - toegekend aan een byte die weinig in onze data voorkomt. - Om dus maximale compressie uit RUNLENGHT te halen kunnen we - het beste gaan zoeken naar een byte die zo weinig mogelijk - voorkomt. Dit houdt in dat het begin van het programma een - beetje veranderd: - - [0] ZOEK MINST VOORKOMENDE WAARDE; - [1] etc. etc. - - Deze stap [0] bestaat ook weer uit een aantal stappen, die - we wat dieper belichten. Eigenlijk is dit gewoon een - algoritme om de minst voorkomende byte te zoeken, maar - aangezien ik helaas niks over de standaard-vormen van zulke - algoritmen heb kunnen vinden heb ik er zelf maar een - ontwikkeld. Het werkt wel, maar zal waarschijnlijk sneller - en beter kunnen. - Werken we stap [0] eens uit: - - [0] ZOEK MINST VOORKOMENDE WAARDE - ( - [1] BYTE-WAARDE = 0; - AANTAL = 0; - [2] LAATSTE DATA-ELEMENT?; - (JA: SLA BYTE-WAARDE EN AANTAL OP IN - FREQUENTIE-TABEL; - BYTE-WAARDE = BYTE-WAARDE + 1; - AANTAL = 0; - [3] BYTE-WAARDE = 0 ?; - (JA: FREQUENTIE TABEL = AF; - END; - ) - (NEE: GA NAAR [2]; - ) - ) - (NEE: - [4] LEES DATA-ELEMENT; - [5] IS DATA-ELEMENT = BYTEWAARDE; - (JA: AANTAL = AANTAL + 1; - GA NAAR [2]; - ) - (NEE: GA NAAR [2]; - ) - ) - ) - - Je ziet dat het algorithme iets omslachtig is en ver is - uitgewerkt, maar door dit uit te voeren hebben we een - frequentie-tabel. Vervolgens hebben we nog een routine nodig - die het minst voorkomende element eruit vist, dus: - - - ( - [1] FREQUENTIE = 0; - TABELPOINTER = FREQUENTIE-TABEL - [2] LEES AANTAL - [3] IS FREQUENTIE = AANTAL?; - (JA: "CMP-ON" = BYTE-WAARDE"; - RETURN; - ) - (NEE: TABELPOINTER = TABELPOINTER + 1; - [4] EINDE FREQUENTIE-TABEL?; - (JA: TABELPOINTER=FREQUENTIE-TABEL; - FREQUENTIE = FREQUENTIE + 1; - GA NAAR [2]; - ) - (NEE: GA NAAR [2]; - ) - ) - - Deze routine werkt ook heel simpel: Eerst zoeken we of er - een AANTAL is dat gelijk is aan FREQUENTIE = 0. Vinden we - dit, dan maken we "CMP-ON" gelijk aan de bijbehorende - BYTE-WAARDE. Vinden we in de gehele tabel geen enkel AANTAL - dat gelijk is aan FREQUENTIE, dan verhogen we de FREQUENTIE - 1 en zoeken we weer vanvoorafaan. Dit doen we net zolang - totdat we een kloppende waarde gevonden hebben. Deze - BYTE-WAARDE dan de minst voorkomende. - Voor de gehele routine houdt dit in: - - -- Complete Source -- - - [0] ZOEK MINST VOORKOMENDE WAARDE - /* Stel de frequentie tabel op */ - ( - [1] BYTE-WAARDE = 0; - AANTAL = 0; - [2] LAATSTE DATA-ELEMENT?; - (JA: SLA BYTE-WAARDE EN AANTAL OP IN - FREQUENTIE-TABEL; - BYTE-WAARDE = BYTE-WAARDE + 1; - AANTAL = 0; - [3] BYTE-WAARDE = 0 ?; - (JA: FREQUENTIE TABEL = AF; - END; - ) - (NEE: GA NAAR [2]; - ) - ) - (NEE: - [4] LEES DATA-ELEMENT; - [5] IS DATA-ELEMENT = BYTEWAARDE; - (JA: AANTAL = AANTAL + 1; - GA NAAR [2]; - ) - (NEE: GA NAAR [2]; - ) - ) - ) - /* Zoek naar minst voorkomende waarde */ - ( - [1] FREQUENTIE = 0; - TABELPOINTER = FREQUENTIE-TABEL - [2] LEES AANTAL - [3] IS FREQUENTIE = AANTAL?; - (JA: "CMP-ON" = BYTE-WAARDE"; - RETURN; - ) - (NEE: TABELPOINTER = TABELPOINTER + 1; - [4] EINDE FREQUENTIE-TABEL?; - (JA: TABELPOINTER=FREQUENTIE-TABEL; - FREQUENTIE = FREQUENTIE + 1; - GA NAAR [2]; - ) - (NEE: GA NAAR [2]; - ) - ) - - /* Begin het echte comprimeren */ - - [1] TELLER = 1; - [2] LEES DATAELEMENT; - [3] {X} <- VOLGENDE DATAELEMENT IN BESTAND; - [4] IS DATAELEMENT GELIJK {X} ?; - - (JA: VERHOOG TELLER; - GA NAAR [3]; - ) - (NEE: - [5] IS TELLER > 3 ?; - (JA: STUUR "CMP-ON"-BYTE NAAR DE CODE; - STUUR DE WAARDE VAN HET DATAELEMENT + - AANTAL KEER VOORKOMEN NAAR DE CODE; - GA NAAR [1]; - ) - (NEE: STUUR TELLER * HET DATAELEMENT NAAR DE - CODE; - GA NAAR [1]; - ) - ) - - -- Next Time: -- - - Zo, nu hebben we een geheel algoritme voor maximale - RUNLENGTH compressie. Het lijkt wat geknutseld, maar werkt - wel. Volgende keer maken we van dit algoritme een mooi - code-programma en als de tijd het toelaat, maken we een - begin met de LZW-methode om data te comprimeren. - - Jan-Willem van Helden - - p.s. Voor de al wat verder gevorderden onder ons, de - pseudo-code die ik gebruik, lijkt verdacht veel op de - hogere programmeer-talen. Daar is die dan ook van af- - geleid. Als je nu een beetje handig bent, kun je deze - routines zo omzetten naar C (+/++/+++) of PASCAL - omzetten. Wie weet besteed ik daar ook nog eens wat - textjes aan. diff --git a/Future Disk/18/Mooblaster Music Cursus.md b/Future Disk/18/Mooblaster Music Cursus.md deleted file mode 100644 index b96c9c8..0000000 --- a/Future Disk/18/Mooblaster Music Cursus.md +++ /dev/null @@ -1,204 +0,0 @@ - MOONBLASTER MUSIC-CURSUS - - - Wat is dit nu weer??? Een cursus MoonBlaster op de - FutureDisk? Ja, inderdaad, je leest het goed; ik heb - inderdaad het snode plan opgevat om deze (en de volgende) - FutureDisks te teisteren met een soort muziekcursus. - - In het verleden zijn er in, op en tussen andere bladen nogal - wat muziekcursussen geweest, en het was mijn bedoeling om - van deze cursus ook iets interessants te maken, en jullie op - die manier het een en ander op muzikaal MSX-gebied te leren. - Zelf ben ik helemaal niet zo muzikaal, maar met wat proberen - kom je echt al een heel eind. Zo is het eigenlijk niet nodig - dat je noten kunt lezen (kan ik ook niet, but who cares) - maar dit is wel handig als je bijvoorbeeld bestaande muziek - wilt namaken. - - WHAT DO I NEED? - - Voor deze cursus heb je vrij weinig nodig, maar een - aantal dingen zijn toch wel vereist, namelijk: - - - MoonBlaster (of een soortgelijk muziekprogramma) - - Een muziekuitbreiding, liefst FM-Pac en/of Music Module - - Veel inspiratie - - Met deze 3 dingen, en natuurlijk een abonnement op de - FutureDisk(NvdR: het laatste geeft natuurlijk de basis!) - moet het toch mogelijk zijn om iets hoorbaars te maken. - Maar nu genoeg geluld; verder met de eigenlijke cursus. - - DE OPBOUW VAN EEN MUZIEKSTUK - - Grofweg zijn de meeste (MoonBlaster-) muziekstukken te - verdelen in een vijftal groepen: - -1. DRUMS -2. ACCOORDEN -3. BASS -4. MELODIE -5. "SPECIAL EFFECTS" - - Als een soort richtlijn kun je de volgende twee manieren van - opbouw onderscheiden: - -Opbouwmethode 1. -================ - - Channel 1: de eerste noot van een accoord - Channel 2: de tweede noot van een accoord - Channel 3: de derde noot van een accoord - Channel 4: de bass - Channel 5: de melodie - Channel 6: de melodie, ditmaal met een soort van echo-effect - Channel 7: zie Channel 1, maar met echo - Channel 8: zie Channel 2, maar met echo - Channel 9: zie Channel 3, maar met echo - - (Accoorden zijn meestal opgebouwd uit 3 noten, maar ook - accoorden van 2, 4 of zelfs nog meer noten zijn mogelijk !) - -Opbouwmethode 2. -================ - - Channel 1: vormt samen met kanaal 2 een soort van "pingel" - Channel 2: zie kanaal 1 - Channel 3: de eerste noot van een (tweestemmig) accoord - Channel 4: de tweede noot van een (tweestemmig) accoord - Channel 5: de bass - Channel 6: de melodie - Channel 7: naar keuze een herhaling van Channel 1 of 3 - Channel 8: naar keuze een herhaling van Channel 2 of 4 - Channel 9: zie Channel 6, maar met echo - - (Over hoe je een echo-effect krijgt of hoe je een pingel - maakt, daar kom ik op een andere FD nog op terug) - -ZIE VOOR VERVOLG IN TEKST 2 !!! - - MOONBLASTER MUSIC-CURSUS(2) - - - - HOE MAAK JE EEN ACCOORD - - Een accoord is meestal opgebouwd uit 3 noten met een - verschillende toonhoogte, maar omdat ook twee-stemmige - accoorden mogelijk zijn zal ik een soort schema geven - waarmee het mogelijk zou moeten zijn om goed-klinkende - accoorden te maken. - - Voor het schema is het misschien wel handig om te weten hoe - een toonladder in elkaar zit. Aangezien de meesten dit wel - weten hou ik het kort: - - C# D# F# G# A# C# D# F# G# - C D E F G A B C D E F G - - Hierboven zie je bijna twee octaven (een octaaf loopt van de - C tot de B) waarin je alle noten ziet die MoonBlaster - aankan. Om nu een accoord te maken kies je een noot, - bijvoorbeeld de A-5 (zo voer je het in MoonBlaster in, het - betekent niks anders dan dat er een A wordt gespeeld op - octaaf 5). Dit is de eerste noot van het accoord. Om nu de - tweede noot te krijgen kies je de noot die drie stappen van - de beginnoot verwijderd ligt, in dit geval dus C-6 - (namelijk van A-5 naar A#5 is een stap, van A#5 naar B-5 is - de tweede, en van B-5 naar C-6 de derde) - Voor de derde noot van het accoord ga je weer uit van de - beginnoot (A-5) en ga je ditmaal zeven stappen verder, - waarna je dus uitkomt op E-6. - - Je kunt echter ook allerlei verschillende variaties maken, - bijvoorbeeld A-5, C-6 en F-6 of A-5, B-5 en D-6. - - En dan nu het langverwachte schema: - - [X+3+7] of [X+4+7] - [X+5+8] of [X+5+9] - [X+3+8] of [X+3+9] - [X+4+8] of [X+4+9] - [X+1+5] of [X+1+6] - [X+2+5] of [X+2+6] - - Het is misschien een beetje onduidelijk, maar ik zal het - uitleggen: het aantal stappen dat volgt na de "of" is - alleen nodig om sommige accoorden goed te laten klinken, - deze stappen komen echter niet zo vaak voor, alleen bij - bepaalde noten (meestal de G of de E). Probeer het zelf - maar, en als het niet klinkt moet je dus de andere stap - hebben. De "X" staat overigens voor de beginnoot. Met zelf - wat experimenteren bereik je ook een hele hoop, en na een - tijdje kun je zelf zo een accoord maken zonder erbij na te - hoeven denken. - - Je kunt van de driestemmige accoorden van het bovenstaande - schema ook heel eenvoudig twee-stemmige accoorden maken door - gewoon een van de noten (meestal de laagste) weg te laten. - Hierbij heb je gelijk nog wat kanalen over voor andere leuke - dingen. - - Als je een MusicModule hebt dan kun je voor je accoorden ook - nog kanaal 7 t/m 9 gebruiken. Je kunt dit natuurlijk ook - voor andere dingen zoals een "pingel" gebruiken, maar uit de - praktijk blijkt dat je, als je deze kanalen inderdaad voor - de accoorden gebruikt je een mooiere achtergrond krijgt. - - -ECHO..... ECho.... echo...... - - Het maken van een echo-effect kan op de volgende manier: - als je bij een kanaal (of in dit geval: de kanalen) een echo - wil maken moet je zorgen dat je hier wel genoeg kanalen voor - vrij hebt. Als je een driestemmig accoord hebt (dat dus drie - kanalen in beslag neemt) moet je zorgen dat je voor de echo - net zoveel kanalen vrij hebt, in dit geval dus drie. - - Stap 1: Als je op kanaal 1, 2 en 3 het accoord hebt moet je - dit kopi�eren naar kanaal 7, 8 en 9 (of andere - kanalen) met het commando [CTRL] + [C]. MoonBlaster - vraagt je nu het te kopi�eren kanaal in te voeren, - in dit geval dus kanaal 1. Vervolgens moet je het - kanaal geven waarheen het gekopi�erd moet worden - (kanaal 7 in dit geval) en tenslotte wordt je - gevraagd het aantal ECHO-steps te geven (van 0-4). - Bij normale snelheid (tempo 19) kun je hier het - beste [2] intypen, bij lagere snelheid kun je - beter een lagere waarde invoeren, en bij hogere - snelheid (tempo 21 of hoger) kun je overwegen om - voor [3] of [4] te kiezen. - - Stap 2: Zet het volume op de kanalen waarheen je gekopi�erd - hebt iets zachter (bij FM-Pac ongeveer 2 stappen, - bij MusicModule ongeveer 10 stappen). - - Stap 3: Detune de kanalen waarheen je gekopi�erd hebt d.m.v. - [F10] of (in de editor zelf) met [T+Y] of [T-Y], - waarbij Y staat voor een getal van 1 t/m 3. Kies in - dit geval de waarde "1". - - Stap 4: Misschien overbodig om te vermelden: op het normale - en op het echo-kanaal moeten dezelfde instrumenten - staan. - - THE END - - Tja, aan de bovenstaande melding te zien heb ik alweer veel - te veel getypt, en daarom verwijs ik jullie nu maar door - naar de disk waar, als de diskruimte het toelaat, nog enkele - voorbeeldjes op staan. Ook vind je hier enkele variaties wat - betreft accoorden. Tot de volgende keer, dan ga ik het hebben - over de drums !! - - Voor suggesties, op- of aanmerkingen kun je terecht bij: - - Erasmusweg 7 - 9602 AB Hoogezand - - - 05980-27379 (na 19.00 u) - - - Jorrith - SOUNDWAVE - Schaap diff --git a/Future Disk/18/Pascal 7.md b/Future Disk/18/Pascal 7.md deleted file mode 100644 index dba6f4e..0000000 --- a/Future Disk/18/Pascal 7.md +++ /dev/null @@ -1,148 +0,0 @@ - PASCAL (7) - - - - ���� We zijn bijna aan het einde gekomen van een reeks PASCAL - ���� cursi. Er zijn nog maar twee onderwerpen die ik wil - ���� behandelen: POINTERS en RECURSIE. Pointers is een soort - ���� data-type in PASCAL en recursie is een soort - programmeermethode. Omdat beide onderwerpen interessant - en (mijns inziens) belangrijk voor een programmeur zijn - besteed ik per onderwerp twee teksten hieraan (zodoende kan - ik dus nog drie teksten en FD nummers vooruit). Ik begin dus - met pointers (les 1). - - Wat is het voordeel van een FILE ten opzichte van een ARRAY: - - oneindig (een file kan in principe oneindig lang zijn) - - flexibele grote (een file kan altijd langer of korter - gemaakt worden) - - weinig geheugen nodig (voor een file is bijna geen - geheugenruimte nodig, wel schijfruimte natuurlijk, maar - daar hebben we tegenwoordig genoeg van) - - Wat is het voordeel van een ARRAY ten opzichte van een FILE: - - snel(1) (ieder element kan onafhankelijk van de andere - opgevraagd worden, dus niet eerst de hele file de revue - laten passeren voordat het laatste element gebruikt kan - worden) -- snel(2) (alles staat in het geheugen en geheugen is v��l - sneller dan disk) -- gemakkelijk (makkelijk te programmeren, denk maar eens aan - een sorteer-algoritme voor files) - - Door genoemde voordelen te combineren zou men een super - gemakkelijk en snel data-type moeten kunnen krijgen. Men heeft - lang (eigenlijk niet, maar voor het verhaal staat dat wel - leuk) gedacht en is met pointers gekomen. Het had snel en - gemakkelijk moeten zijn. Het is snel, maar zeker NIET - gemakkelijk. Wat zijn pointers dan wel vraag je je af? - - snel (alles staat in het geheugen) - - oneindig (zolang er geheugen is kunnen er pointers - aangemaakt worden) -- flexibele grote (tijdens programma executie kunnen nieuwe - pointers aangemaakt worden) - - Je kunt je nu natuurlijk nog niets bij pointers voorstellen, - maar dat ga ik even veranderen. Wat is een pointer namelijk in - de computer (hoe werkt het)? Een pointer is (zoals de naam al - zegt) een wijzer(NvdR: grote meid!). Genoemde wijzer kan - wijzen naar niets of naar een data-element. Wijst het naar - niets, dan wijst hij naar NIL (gereserveerd woord), dat - (waarschijnlijk) het getal 0 is en dus geheugenruimte 0 is. - Wijst het naar een data-element dan is de pointer het adres - waar dat data-element gevonden kan worden. Dus als ik een - pointer A heb, dan kan de inhoud van A NIL zijn of - (bijvoorbeeld) #a084. NIL wil zeggen dat de pointer nergens - naar wijst en #a084 dat de pointer naar adres #a084 wijst. - Staat op adres #a084 het getal 10, dan wijst de pointer dus - het getal 10 aan. Grafisch wordt een en ander vaak als volgt - weergegeven: - - A - +-+ +----+ - | |--->| 10 | - +-+ +----+ - - Bovenstaand geval is als een pointer een byte (1 byte in het - geheugen) aanwijst. Er zijn dus wel 3 bytes nodig om een en - ander goed te laten werken (2 voor de pointer (16 bits adres) - en 1 voor het data-element (byte)). Een pointer kan elk data- - type aanwijzen dat de gebruiker maakt, hierdoor is het - mogelijk om een zogenoemde gelinkte lijst te maken (een - pointer die naar een pointer wijst die naar een pointer wijst - die naar een pointer wijst die naar een pointer wijst die naar - een pointer wijst die naar een pointer wijst die naar een - pointer wijst die naar een pointer wijst die naar een pointer - wijst ...............). Op zich heb je daar dus niets aan, - maar als je alle pointers nu eens naar een RECORD laat wijzen - dat een data-element EN een pointer bevat, dan kom je al een - heel eind. Grafisch ziet dat er als volgt uit: - - Hoofd - +-+ +---+-+ +---+-+ +---+-+ +---+-+ +---+-----+ - | |--->| 5 | |--->| 9 | |--->| 4 | |--->| 0 | |--->| 1 | NIL | - +-+ +---+-+ +---+-+ +---+-+ +---+-+ +---+-----+ - - Allemaal heel leuk, maar hoe gebruik je dit (oftewel geef een - programma, dan zien we tenminste iets). Kijk maar eens naar de - file "POINTER.PAS" op deze diskette, daar staat een voorbeeld - in. - - Bij TYPE staat de declaratie van een pointer: - typenaam1 = ^typenaam2 (* ^ staat voor 'pointer naar' *) - - Hier is dus wel iets geks aan de hand, want Wijs is een - pointer naar Element, maar Element is nog niet bekent...... - MAG DAT???? Ja, dat mag, als uitzondering. Zouden we Element - en Wijs in de declaratie omdraaien, dan zouden we namelijk een - soortgelijk probleem hebben omdat in Element, Next van het - type Wijs is. Bij pointers mag er dus een type vooruit genoemd - worden. Overigens wel in de volgorde zoals in het voorbeeld - staat (dus eerst het pointer-type en daarna pas het type waar - de pointer naar wijst). - - De variabele declaratie zal geen problemen opleveren, dit in - tegenstelling tot het hoofdprogramma. Het eerste nieuwe dat we - tegenkomen is 'Hoofd:=NIL'. Aangezien Hoofd nog een - ongedefinieerde waarde heeft, maken we deze eerst gedefinieerd - (vanaf nu wijst Hoofd dus nergens naar). Het volgende is - 'NEW(Hulp)'. Hier wordt een geheugenplaats aangevraagd voor - het data-type van Hulp. (voor de opdracht NEW wijst de pointer - Hulp naar een ongedefinieerde plaats in het geheugen. Bij de - NEW opdracht wordt er in het geheugen gezocht naar een plaats - waar het data-type van de pointer inpast (in dit geval een - integer en een pointer)). Deze geheugenruimte wordt dan - gereserveerd voor zulk een data-type en de pointer wijst vanaf - nu naar genoemde plaats in het geheugen). - - De toekenningsopdrachten zijn min of meer vanzelfsprekend als - je weet dat pointer^ het data-element is (dus Hoofd^ is een - RECORD met twee velden (Waarde en Next), de inhoud van Waarde - is dus te bereiken met Hoofd^.Waarde). Wel moet ik vermelden - dat als je een pointer (bijvoorbeeld Hulp) zelf veranderd, dat - de computer dan niet de geheugenruimte vrijmaakt waar de - pointer naar wijst. Door alsmaar 'NEW(hulp)' als opdracht te - geven zou het geheugen dus vollopen (zorg ervoor dat je het - adres van het data-element ergens bewaart, anders ben je het - voorgoed KWIJT in het walhalla van je computer geheugen). In - het voorbeeld programma raak ik niets kwijt (ook visueel - zichtbaar) omdat ik een gelinkte lijst maak (ik laat de - elementen naar elkaar wijzen). - - Wil je de geheugenplaats waar een pointer naar wijst vrij - maken dan gebruik je DISPOSE (zoals ook op het einde van het - programma te zien is). - - Zo, dat was het dan alweer. Volgende keer meer, veel meer over - pointers, maar voor nu 2 opdrachten om jezelf te testen: - - (1) Zie voorbeeld programma, maar nu de getallen in volgorde - van invoer in de lijst plaatsen. - (2) Zie voorbeeld programma, maar nu de getallen gesorteerd in - de lijst plaatsen. - - Veel plezier, - - Jeroen 'Pointer to FD' Smael - - (NvdR: 'Pointer to Smael: ^Shut up!) diff --git a/Future Disk/18/Undocumented Z80 code.md b/Future Disk/18/Undocumented Z80 code.md deleted file mode 100644 index 67df4ff..0000000 --- a/Future Disk/18/Undocumented Z80 code.md +++ /dev/null @@ -1,57 +0,0 @@ - -- MCODE -- - - - ���� - ���� - ���� - ���� - ���� - - Stop de persen, gooit uw PC uit het raam, speelt uw MOD's op - via uw Simpl, schrijf u in voor een survival-tocht in - Grozny, omhels S.B. en wordt lid van de EO. Wat is immers - het geval? - - Sinds ik mijn tijd verdoe op de TU in Eindhoven, leer je - allerlei dingen over computers en kom je andere MSX-ers - tegen. Zo hoorde ik laatst van Zelly (wie dat is zoek je - zelf maar uit) dat er alweer een ongedocumenteerde - instructie van de Z80 bestaat: - - IN F,(C) - - Huh, was dat niet een R800-commando?? In m'n Z80? - Jawel hoor, die klojo's van Zilog hebben ons al bijna 20 - jaar instructies verzwegen (durven ze wel stelletje boeren). - Een daarvan is dus deze. Je bereikt hem door in WBASS-2 in - de editor het volgende te zetten: - - IN (HL),(C) - - Als opcode houdt dit in: EDh,70h. En verdomt, zo staat ie - ook gedocumenteerdt in de R800-manual. - Intern doet de Z80 eigenlijk de volgende dinges: - - IN A,(C) - OR A - - Zo zou deze opcode dan ook kunnen maken, ware het niet dat - IN F,(C) register A ongeschonden houdt. - - Wat kan ik nu met deze instructie ??? - - Wel, je kunt er heel gemakkelijk een I/O poort mee in de - gaten houden en hoeft geen OR-ren of AND-en meer te - gebruiken. Kortom sommige dingen kunnen sneller! - - Programmeurs van Nederland, omhels deze instructie en - waardeer hem alsof hij er altijd al was. Schroom je niet om - 'm te gebruiken. Hij is eindelijk legaal verklaart !!! - - Veel plezier met deze instructie, - - Digital JW - - p.s. Er hebben mij geruchten bereikt dat de Z80 ook zou - kunnen vermenigvuldigen. Laten we dat eens gauw uit- - proberen... diff --git a/Future Disk/19/Basic Cursus 8.md b/Future Disk/19/Basic Cursus 8.md deleted file mode 100644 index 3d5c071..0000000 --- a/Future Disk/19/Basic Cursus 8.md +++ /dev/null @@ -1,77 +0,0 @@ - Basic Cursus (7) - - - ���� - ���� - ���� - ���� - - OUT&HFE en ander ge-emmer - - In Basic heeft de gebruiker eigenlijk maar weinig geheugen - tot zijn beschikking. &H0000-&H7FFF is immers Rom, - op &H8000-&HBFFF staat je basic programma, en alles boven - &HE000 is eigenlijk ook al linke soep... Blijft dus over - &HC000-&HE000, en das nie bar veel! In die 8Kb kun je - natuurlijk wel een zooitje strings en variabelen kwijt maar - als je ook maar iets bv op sector in wil laden of een - aantal sampletjes wil afspelen dan zit je al in de knoop. - Een redelijk onbekende -onbeminde- methode is om basic - gewoon op C000 te flikkeren en daardoor komen alle banks - van 8000-BFFF weer vrij. For the ignorant, a little scheme: - - I Geheugen I Vrije Banks I - -------------------------- - I 64Kb I 1-3 I - I 128Kb I 1-7 I - I 256Kb I 1-15 I - I 512Kb I 1-31 I and so on..... - -------------------------- - - Als je dit geintje dus uitvoert heb je in ��n keer een hele - zwik geheugen tot je beschikking, wat overigens heerlijk is. - Dit truukje werkt echter alleen met de interne of op de op - dat moment ingeschakelde mapper. Twee mappers in basic - gebruiken kan wel maar dat ga ik niet helemaal uitleggen. - Eerst zul je dus Basic op $C000 moeten zetten, daarna moet - je natuurlijk nog weten hoe je welke mapper bank in moet - schakelen. Mapper bank0 is niet beschikbaar, dit is normaal - gesproken &HC000-&HFFFF waar Basic z'n administratie neerzet - en de gebruiker nog even rond kan poken/peeken. Mapper bank - 1 wordt door Basic gebruikt om de programma-data in op te - slaan, hier staat dus normaal je programmaatje in. Nu gaan - we dat programmaatje naar &HC000 verplaatsen. Theoretish - mag dat niet omdat je dan in de knoop kan komen met je - systeem variabelen die Basic in die bank opslaat. In de - praktijk valt dit over het algemeen wel mee. 't Is mij - in iedergeval nog nooit gelukt. Dit betekent namelijk een - listing die Tokenized al meer dan 8Kb zou zijn. Grote jongen - die dat bij elkaar typt! Nu is bank1 dus ook vrijgekomen - aangezien je programmaatje daar nu niet meer staat. Je kunt - dus -behalve bank0- alle banks gebruiken (Zie schema). Dan - nu 't eigenlijke programmaatje wat je dan krijgt: - - 10 ' MEMTEST.BAS - 20 IFPEEK(&HF677)<>&HC0THENPOKE&HF677,&HC0:POKE&HC000,0: - RUN"MEMTEST.BAS" - 30 FORP=1TO255:OUT&HFE,P:POKE&H8000,55:NEXTP - 40 FORP=1TO255:OUT&HFE,P:IFPEEK(&H8000)=55THENPG=PG+1:NEXTP - 50 PG=PG+1:PRINT PG*16;"KB GEHEUGEN" - - Nu is dit maar een stom programmatje maar wat je nu feitelijk - met die pages doet boeit eigenlijk niet. Pleur d'r maar eens - graphics of muziek neer. Samples wil trouwens ook prima. Als - je 't echt netjes wil doen pleur je alles wel weer keurig - terug als je klaar bent. Dus krijg je: - - 60 POKE &HF677,&H80:POKE&H8000,0 - - Als je daarna namelijk andere programma's gaat laden die er - niet op rekenen dat basic op $C000 staat wil dat nog wel - eens de soep in lopen. Het is overigens ook wijsheid om - met CTRL op te starten aangezien basic dan wat minder - geheugen nodig heeft voor z'n drive administratie. - - Well that's all, bye.... - - Tobias 'I love my 512Kb mapper' Keizer diff --git a/Future Disk/19/Basic voor beginners.md b/Future Disk/19/Basic voor beginners.md deleted file mode 100644 index 395955d..0000000 --- a/Future Disk/19/Basic voor beginners.md +++ /dev/null @@ -1,89 +0,0 @@ - BASIC CURSUS - - algemene hints voor beginners - - - ���� - ���� - ���� - ���� - - - Ja, even voor de al iets verder gevorderden onder u. Deze keer - staat er eigenlijk niets in voor jullie dus, err, why don't - you go tie your dick in a knot?!(NvdR: ik zal je maar niet - de 993 redenen noemen) - - Even een aaqntal tips voor de beginnertjes. Gezien 't feit dat - de basic interpreter uit ons lieve MSX-je nog langzamer is dan - mijn oma van 94 moet je erg opletten met wat je doet in je - programmaatje. Let hierbij vooral op loops omdat deze vaker - worden uitgevoerd. Eerst dus even een paar DO's en DONT's. - - Vermijd REM of ' in een loop omdat deze vreemd genoeg tijd in - nemen. Je zou haast verwachten dat basic gewoon door gaat na - het tegenkomen van een REM of ' maar hij loopt vreemd genoeg - eerst de hele regel door. Nadat je dus je REM's keurig voor of - na de loop heb gezet ga ik je opeens vertellen dat je het ' - tekentje eigenlijk maar niet moet gebruiken omdat deze vreemd - genoeg 3 bytes inneemt terwijl het drie letters tellende woord - REM maar 1 byte inneemt. Nu gebruik ik zelf gewoon altijd ' - maar mocht je dus ooit in geheugen probleemples komen kun je - altijd nog je '-tjes vervangen door REM's. Maar het best vind - ik nog altijd helemaal geen REM's of '-tjes. - - Spaties zijn ook een probleem, deze kosten namelijk tijd. - Ik persoonlijk typ gewoon geen spaties in m'n basic werk maar - wat ook prima werkt is eerst typen en later als alles af - is(�n werkt) de spaties er uit halen. Pas wel op: soms zijn - spaties verplicht om alles nog goed te laten werken. - - Wisselen tussen twee waarden. - Ook dit kost nog wel eens tijd. Vaak krijg je allerlei IF THEN - constucties in je programmaatje die niet al te snel zijn. - Kijk altijd eerst of 't een en ander niet met een XOR te - verhelpen is. XOR's zijn namelijk heel snel. Als je dus bv - wisselen moet tussen 2 en 0 wat bv bij het veranderen van - de frequentie nog wel eens 't geval is, krijg je meestal - iets als: - - 10 ' 0 = 60Hz 2 = 50Hz - 20 IF HZ = 0 THEN VDP(10)=2 : HZ=2 : GOTO 40 - 30 IF HZ = 2 THEN VDP(10)=0 : HZ=0 : GOTO 40 - 40 BLA BLA BLA.... - - Veel sneller is - - 10 ' 0 = 60Hz 2 = 50Hz - 20 HZ=HZ XOR 2 : VDP(10)=HZ - - Of nog sneller (en technisch gezien de enige goede manier) - - 10 VDP(10)=VDP(10)XOR2 - - Even voor die mensen die niet weten wat een XOR doet: - een XOR doet niets anders dan het (de) aan gegeven bit(s) van - een byte omgooien. Als (zoals bij 't voorbeeld) de byte dus - &B00000010 is en de XOR &B00000010 is wordt bit twee dus ook - steeds omgegooid. Mensen die niet weten hoe 't binaire stelsel - in elkaar steekt raad ik aan eens hun BASIC manual door te - lezen waar dit soort dingen vaak wel instaan. Hierbij raad ik - aan het gedeelte over het octale stelsel over te slaan aan- - gezien dit eigenlijk nooit wordt gebruikt in BASIC(NvdR: in - andere talen ook vrijwel niet heb ik me laten vertellen door - Jan-Willem!). - - Voor jullie beginners raad ik dus aan eens goed met die XOR's - en andere operaties in BASIC te gaan spelen want het scheelt - echt wel als je die goed onder de knie heb. - Lieden die echter denken dat het nodig is om uit het hoofd de - getallen van 0 tot 255 van DEC naar HEX en van HEX naar BIN - te kunnen omrekenen hebben wel een erg hoog doel en kunnen - maar beter door gaan met de MC cursus elders op dit mag. - Toegegeven, 't is wel handig om sommmige waarden in HEX, - DEC en BIN uit 't hoofd te kennen. - - Well boys, that's about it for now. - Read the rest of my shit in the next txt-file. - -Tobias 'kill that space' Keizer diff --git a/Future Disk/19/Looplichtjes 2.md b/Future Disk/19/Looplichtjes 2.md deleted file mode 100644 index a369bb8..0000000 --- a/Future Disk/19/Looplichtjes 2.md +++ /dev/null @@ -1,39 +0,0 @@ - LOOPLICHTJES - - ���� - ���� - ���� - ���� - - Enige tijd geleden, FD #15 om precies te zijn, plaatste ik een - artikeltje over looplichtjes met daarbij een schemaatje om 't - zooitje te bouwen. Ik beloofde daarbij ook een programmaatje - om de aansturing wat makkelijker te maken. Welnu, van dat - programmaatje is nooit al te veel gekomen wegens tijdgebrek - maar een aantal bellers meende dat 't zonder dat - programmaatje niet mogelijk was om 't looplichtje aan te - sturen. Dit is echter niet het geval. Op FD #15 stond namelijk - een programma dat naar de naam 'LOOPLICH.BAS' luisterde. Met - dit programma was 't wel degelijk mogelijk om het looplichtje - aan te sturen. Dat verklaart hopelijk 't ��n en ander en het - is dus ook niet zo dat ik de lezers van de FD compleet - belazer. Aansturen was wel degelijk mogelijk, ook in de tijd - van FD #15 al. Ik heb nu nogmaals het programma op de - disk laten zetten en ik hoop dat het eventuele misverstand - uit de lucht is geholpen. In het vervolg raad ik leden van - de FD dan ook aan om bij problemen niet contact op te nemen - met de redactie maar met mij persoonlijk aangezien ik zelf - meer verstand heb van mijn eigen brouwsels dan onze - -onkundige- redactie. Bij deze dan nogmaals mijn adres en - telefoonnummer en miscchien dat mijn telefoonnummer - ook door de redactie kan worden opgenomen bij de helplines - aangezien ik nooit te beroerd ben om de mede MSXer te helpen. - (NvDR: je bent te goed voor deze wereld, Keizer!) - - Tobias Keizer - Oudestraat 21-2 - 8261 CC Kampen - Tel: 05202-31348 - Fax: 05202-31348 - - Tobias 'Light Emiting Brain' Keizer diff --git a/Future Disk/19/MSX2+ Schermen in BASIC.md b/Future Disk/19/MSX2+ Schermen in BASIC.md deleted file mode 100644 index ce716e0..0000000 --- a/Future Disk/19/MSX2+ Schermen in BASIC.md +++ /dev/null @@ -1,169 +0,0 @@ - 2+ SCHERMEN IN BASIC. - - - ���� - ���� - ���� - ���� - - - Rond 1988 dacht men bij ASCII, jongens we zijn 't zat, d'r - moeten meer kleuren in die MSX2. Men is eens goed gaan - nadenken, en dat ging die sukkels daar bij ASCII niet erg - goed af. Want wat hebben die eikels toen besloten: Wel meer - kleurtjes, maar niet meer VRAM, en ja, dan krijg je gezeik. - Als de heren bij ASCII de volgende MSX serie (2+) nou gewoon - 512KVram hadden gegeven was er niets aan de hand geweest, - maar dat wou niet volgens ASCII. Maar goed, bij ASCII zijn - ze toen gaan nadenken hoe ze zo veel mogelijk kleuren in zo - weinig mogelijk VRAM konden krijgen en dat werd dus het YJK- - systeem. Toen ze alles af hadden hadden de heren bij ASCII - zelf ook wel door dat 't niets was en hebben toen ook maar - besloten het geplande MSX3 systeem -met Z800!- en dus de - nieuwe V9958 te laten voor wat het was en hebben toen maar - eerst even de 2+ uit gebracht die nog wel een Z80 had maar - dus wel de nieuwe V9958. Verder dan die V9958 is het nooit - gekomen, het V9978 idee werd in een vroeg stadium al - afgeblazen wegens te hoge kosten en te weinig potentiele - kopers. -ik had toen nog geen MSX- en de V9990 werd ook een - flop doordat het een poging was om meer computersoorten - tegelijk te bereiken. Op de MSX moeten wij het dus doen met - een zeer slome en in efficiente V9958. Dat er weinig mogelijk - is met de V9958 is wel duidelijk. Digi's worden perfect en - daar houdt 't wel zo'n beetje mee op. Toch valt 't allemaal - nog wel een beetje mee. Als je maar weet wat je doet. - - COLORSPILL - - Screen 2 is al net zo onbruikbaak als screen 12. Hetzelfde - verhaal geldt hier namelijk als bij Screen 12. Te veel - kleuren in te weinig geheugen. Toch zijn heel behoorlijke - resultaten te behalen op screen 2. Kijk maar naar de hele - Nemesis serie en klonen die Konami heeft uitgebracht. Als - jij een spel als Nemesis III speelt op je MSX2 werkt het toch - allemaal echt in screen 2. Ook al zijn de kleuren iets - aangepast. Ik ben er echt van overtuigd dat dit ook kan in - screen 12. Maar dan moeten er wel eerst fatsoenlijke - tekenprogramma's komen voor dit scherm. - - DE 'LOGICA' - - Om te begrijpen hoe de V9958 te werk gaat moeten we eerst even - kijken hoe alle data in 't Vram wordt gezet. - - Bit: | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | - -------------------------------------------------------- - Byte 1 | H | H | H | H | H | G | G | G | - Byte 2 | H | H | H | H | H | B | G | G | - Byte 3 | H | H | H | H | H | R | R | R | - Byte 4 | H | H | H | H | H | B | R | R | - -------------------------------------------------------- - - Hierbij staat de H voor helderheid, de R, de G en de B voor - respectievelijk R G en B. Een voorbeeldje. Iedereen klaagt - altijd over de kleur blauw die zo verdomd moeilijk op 't - scherm is te krijgen. Nou, als je weet wat je doet valt dat - wel mee. - - VPOKE &H0000,&B00000000 : VPOKE &H0001,&B00000100 - VPOKE &H0002,&B00000000 : VPOKE &H0003,&H00000100 - - De bits die voor blauw staan gewoon op 'aan' zetten en - klaar! Lastig is dus wel dat je altijd binnen een groepje - van 4 bytes moet blijven. En dat is dus 't hele probleem van - Screen 12. Verder is er niets aan de hand. De Helderheid kun - je gewoon vrij per pixel instellen zonder dat er allerlei enge - dingen gebeuren.. - Dat betekent dus dat er 32 helderheden per pixel kunnen - worden ingesteld en ik denk dat dat echt een sterk punt is - van Screen 12!! Als tekenprogramma's nou eens gewoon gebruik - maakten van de uit Screen5 bekende balkjes voor RGB en dan - nou eens gewoon die kleur in de 32 helderheden zou afbeelden - werd 't leven van de tekenaar op screen 12 al een heel stuk - makkelijker. Denk ik tenminste!! Goed, met deze gegevens - kunnen we al een heel eind verder, maar waarom werkt - Screen 10 dan wel goed in basic? Nou Screen10 bestaat gewoon - niet. Als dat alles niet een heel stuk duidelijker maakt - weet ik 't ook niet meer! Nee, Screen 10 bestaat aleen in - basic, de basic interpreter gaat met screen 10, dat - eigenlijk gewoon Screen 11 is, zodanig om dat alle - instructies dezelfde zijn als die uit Screen 8, zij het dat - de kleur en van 0 tot 15 lopen. Hoe werkt dit dan? - - Bit: | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | - ------+-----+-----+-----+-----+-----+-----+-----+-----+ - Byte 1| x | x | x | x | S | G | G | G | - Byte 2| x | x | x | x | S | B | G | G | - Byte 3| x | x | x | x | S | R | R | R | - Byte 4| x | x | x | x | S | B | R | R | - ------+-----+-----+-----+-----+-----+-----+-----+-----+ - - De x is hier variabel. Dit komt door de S in het geheel. - Die S is namelijk een Switch. Staat deze 'uit' dan geldt de - normale verwerking van de bits en zijn alle x bits de - helderheid.. Staat zo'n bit echter 'aan' dan schakelt - 'screen5' in en worden de xbits de 4bits kleurcodes die we - van screen5 kennen. De basis kleur van de vier pixels blijft - hetzelfde zodat zowel dat 16 paletkleur en als de 65536 - Screen10 kleuren kunnen worden afgebeeld in de Screen10 mode. - Omdat dus een bit wordt gebruikt voor de Switch gaat dus wel - de helft van de helderheden verloren aangezien er nog maar - 16 helderheden kunnen worden gemaakt. Een plaatje van - Screen12 naar 11 converteren is dus geen probleem aangezien - je alleen bit3 maar 'uit' hoeft te zetten. Dit kan gewoon - met een Box in 'kleur' &B 11110111 waar vervolgens een AND - op los moet worden gelaten waardoor bit3 altijd nul wordt - en de andere bitjes onaangetast blijven. - Op de disk staat een basiclisting die 256*212=54272 kleuren - op 't scherm tovert. Meer was op zich 't probleem niet zij - het dat er niet meer pixels beschikbaar zijn in screen 12 en - ik de pest heb aan interlacing. Maar hoe ga ik dan te werk? - Simpel, je begint door met een simpel rekentruukje alle - mogelijke (4096) basis kleuren op het scherm te toveren en - die vervolgens per basiskleur naar 32 pixel te copien. Je - hebt namelijk van elke basiskleur 32 pixels nodig om daar - later je H bits op aan te passen om de 32 helderheden te - krijgen. Als dan het hele scherm vol staat met van alle - basiskleuren 32 pixels kun je je helderheden er overheen - XORen zonder dat je de basis kleurbits aantast. Hiervoor - gebruik ik een truuk die eigenlijk niet mag maar goed, - niemand heeft het door. Dat kleuren aantal is natuurlijk - theoretisch want 't komt ongetwijfeld wel op een kleiner - aantal uit. - - &B11111101,&B11111000,&B11111000,&B11111000 - - is natuurlijk 't zelfde als - - &B11111011,&B11111000,&B11111000,&B11111000 - - Maar dat zal een ieder duidelijk zijn, als je twee 'groen' - bitjes aan zet maakt 't natuurlijk niet uit welke twee dat - zijn..ook al denkt mijn programma daar anders over. Waarom - ASCII ook zegt dat er maar 19000 nogwat kleuren zijn is mij - ook een raadsel. Van screen 5 zei men toch ook dat er een - palet uit 512 verschillende kleuren mogelijk was? R3 G3 B3 is - bij mij 't zelfde als B3 G3 R3 of niet soms? Nou weet ik ook - wel dat 't verschil tussen helderheid 31 en 30 niet te zien - is en dat als twee bits 'groen' aan staan het niet uit maakt - welke dat zijn maar laten we gewoon zeggen dat screen12 - 2 tot de 12e * 32 = 131072 kleuren heeft zodat we tegen al - dat Super Nintendo geweld op kunnen met ons 2plus-je. Tegen - PCers zeggen we dan gewoon weer 131072 basiskleuren in - 16 helderheden zodat hun 1,6 miljoen ook weer met bijna - 500000 is over schreden en dan kunnen we er weer tegenaan met - ons MSXje. Ik hoop dat ik met deze korte uitleg 't een en - ander duidelijk heb gemaakt en HOO WACHT!!! voor dat ik - het vergeet, of dat programmaatje van mij werkt weet ik eigen- - lijk niet... Ik heb namelijk een monochrome monitor hangen aan - m'n MSX-Turbo-R (wat ben ik ook een stakker.) zodat alle kleur - en zo'n beetje 't zelfde lijken en of ze dus ook echt verschil - lend zijn weet ik niet. Niet boos worden als 't niet zo is oke - boyz!? Oh ja, ik was aan het afsluiten dus daar ga ik dan maar - weer mee verder. Ik hoopte geloof ik dat ik jullie weer 't een - en ander heb duidelijk gemaakt en dat was 't dan wel voor deze - keer want 3 basic cursussen op een nummer is wel echt genoeg.. - - Tot de volgende keer dan maar!! - - Tobias "God, i'm perfect!" Keizer diff --git a/Future Disk/19/Mcode Special 1.md b/Future Disk/19/Mcode Special 1.md deleted file mode 100644 index 915d470..0000000 --- a/Future Disk/19/Mcode Special 1.md +++ /dev/null @@ -1,181 +0,0 @@ - - MCODE SPECIAL(1) - - - Welkom bij deze speciale aflevering van de programmeercursus. - Dit keer geen gezwam over Z-80 instructies, maar de komplete - uitleg over hoe een spel in machinetaal geprogrammeerd wordt. - Hierbij wordt aangenomen dat je de vorige afleveringen van - deze programmmeercursus allemaal gevolgd hebt, dan wel - zelf kennis hebt opgedaan over de Z-80 instructies en het - gebruik daarvan in machinetaal programma's. - Ik zal een poging doen om zoveeeeel uitleg te geven dat - iedereen, die interesse heeft deze tekst kan volgen. Mocht - het een of andere nog niet duideljik zijn: mijn - telefoonnummer is 04746-1655 (voor 7 uur ben ik normaal niet - thuis). - Als voorbeeld van een spel wordt het bekende spel - MINE-SWEEPER genomen, aangezien de omvang van de routines - van dit spel niet zo groot is, maar er toch erg veel van - geleerd kan worden over spelprogrammeren. - Alvorens verder te lezen raad ik je aan het spel eerst - zelf een paar keer te spelen en voor jezelf al een beeld - te vormen hoe je een en andere zou programmeren. Voor de - mensen met printer: het kan erg handig zijn om de listing - van het spel op papier te hebben om ze erbij te kunnen - houden terwijl je deze tekst leest(NvdR: staat op de disk - onder de filenaam MINESW.GEN.) - - Hier volgt eerst een korte beschrijving en uitleg van het - spel voor degenen die het spel niet kennen. - Het is de bedoeling om alle mijnen in het mijnenveld, - voorgesteld door een scherm met vierkantjes, te vinden en - op veilig te stellen. - Met de muis of de cursortoetsen kan een pijltje bestuurd - worden en met een druk op de spatiebalk of linkerknop kan - gekeken worden of zich onder een vierkantje - (=hokje/blokje/veld) een mijn bevindt of niet. - Bevindt zich geen mijn op de plaats waar gedrukt werd wordt - in het hokje een cijfer afgebeeld dat aangeeft hoeveel - mijnen zich rondom het blokje bevinden. Een leeg hokje - betekent dus geen mijnen op de 8 aangrenzende plaatsen; dit - moet er toe leiden dat alle 8 aangrenzende hokjes automatisch - zichtbaar gemaakt worden (totdat er geen omliggende hokjes - meer leeg zijn!). - Wordt op een mijn gedrukt betekent dit automatisch het - einde van het spel, alle mijnen worden dan nog even - zichtbaar gemaakt. - Met een druk op SHIFT of de tweede muisknop kan een hokje - op veilig gesteld worden hetgeen m.b.v. een vlag aangegeven - wordt. - Zijn alle mijnen op veilig gesteld en alle niet mijnen - zichtbaar gemaakt dan is het spel gewonnen (tevens ten - einde). - - We hebben om dit spel te programmeren dus (hoofdzakelijk) - nodig: - - 0. Een routine, die het nodige initialisatiewerk doet. - 1. Een muisroutine/cursorroutine, die een pijltje (een sprite) - over het scherm kan bewegen. - 2. Een routine die de 1e muisknop/spatiebalk uitleest en kijkt - of er op de coordinaten waar het pijltje zich nu bevindt - een mijn bevindt - 2a. zo ja, het hele veld zichtbaar gemaakt wordt - 2b. zo nee, uitzoekt hoeveel mijnen rondom zitten en dit - nummer afdrukt of - 2c. als er geen mijnen rondom zijn de onliggende hokjes - automatische zichtbaar maakt tot er geen lege omliggende - hokjes meer zijn. - 3. Een routine, die uitzoekt hoeveel hokjes nog zichtbaar - gemaakt moeten worden voor het spel gewonnen is/ - 4. Een routine, die de SHIFT-toets en tweede muisknop - uitleest en hokjes op veilig kan stellen/weer onveilig - kan maken. - - - STARTEN - - Uitgegaan wordt van 1 programma, geschreven in machinetaal, - m.b.v. TED of GEN80. - Besloten wordt nu eerst het spel in Screen 5 te gaan maken, - voor het pijltje een sprite te kiezen en de rest van de - grafische commando's op te lossen met COPY's. - M.b.v. Spen wordt op de eerder beschreven methode (machinetaal - cursus zoveel) een pijl getekend als dubbele sprite - (dus 2 sprites over elkaar heen, om meer kleuren te kunnen - gebruiken) en de DATA naar TED gehaald (zie labels SPRCOL en - SPRPAT). - Besloten wordt het scherm op te delen in 16x16 blokjes, die - de mijnenvelden voorstellen. OP het scherm passen dan - 256:6=16 blokjes in x richting en 212:16=13.25 --> 13 blokjes - in vertikale richting. In DD-Graph worden nu eerst de - benodigde 16x16 symbolen getekend, die we in het spel nodig - hebben(in volgorde zoals ze op de page staan): - -xco 0 16 32 48 64 80 96 112 128 144 160 176 - Leeg H.,1, 2, 3, 4, 5, 6, 7, 8, Onzichtbaar H.,Vlag,Mijn - - (H. = hokje) - - Besloten wordt op deze blokjes op Page 1 neer te zetten op - Yco 0. - (xco=x-coordinaat en yco=y-coordinaat). - Het spel zelf zal zich gaan afspelen op Page 0. - In DD-Graph wordt het gebruikt palet tevens omgezet naar - DATA, die we in het hoofdprogramma kunnen gebruiken (zie het - label:PALET). - - In een Basic-programmatje (n.l. "MINESW.BAS") worden deze - blokjes m.b.v. een Copy commando op de juiste plaats gezet - en dit programma start tevens het hoofdprogramma "MINESW.COM" - op. - - We kunnen nu eindelijk beginnen met het echte werk: het - hoofdprogramma - - - HET HOOFDPROGRAMMA - ("MINESW.GEN") - ------------------ - -Initialisatie - - Er wordt gebruik gemaakt van het lijstje met benodigheden voor - het spel en we beginnen dus uiteraard met het - initialisatiewerk. Omdat we het programma vanuit basic willen - kunnen opstarten m.b.v. BLOAD (en GEN80 slechts .COM-files - maakt voor op te starten vanuit DOS) komt nu eerst een HEADER: - - DB #FE ; geeft aan dat dit een "BLOAD-file" is - DW ST ; startadres - DW EN ; eindadres - DW ST ; beginadres - - Bovendien wordt aan een aantal BIOS-adressen een naampje - gegeven, zodat we later in het programma CALL GTTIG (=get - trigger) kunnen gebruiken i.p.v. een onduidelijke CALL #D8. - - Initialisatie van de sprites gebeurt in de subrotine INIT, - omdat het onhandig is later telkens de lange initialisatie- - routines te moeten overslaan, terwijl je iets in het - hoodfprogramma wilt veranderen. In deze routine, worden de - spritekleuren en patronen in het videogeheugen opgeslagen, - de sprites "aan"-gezet en op 16x16 formaat. - Het besturen van een sprite komt nu er op neer dat je de - coordinaten in de spriteattribuutgeheugen veranderd - (label:SPRATT). - Merk op dat deze INIT afsluit met een routine SETSPRITES, - die de sprites de eerste keer neerzet, maar die later - opnieuw aangeroepen kan worden als er sprites bewogen - worden! - De routine wordt aangeroepen met CALL, hetgeen betekent - dat er na een RET terug gesprongen wordt naar het - aanroeppunt. De routine sluit echter af met een JP naar - een biosadres, waar automatisch een RET gevonden wordt - m.a.w.: - - CALL+RET=JP - - Voor verdere uitleg over sprites : zie de eerder verschenen - FUTUREDISK met de cursus over sprites. - - Nadat de sprites zijn geinitialiseerd wordt het Palet - aangezet, door in HL het adres van de paletgegevens - (uit DD-Graph) te zetten en de subroutine SETPAL aan te - roepen. Verder uitleg over SETPAL voert hier te ver aangezien - dat meer in een VDP-cursus thuishoort. Neem maar van mij aan - dat de routine werkt en je hem zonder problemen in je eigen - programma kunt gebruiken. - - Programmeertechnisch gezien kun je nu het beste verder - gaan met de besturing van de pijl, maar om even de lijn van - het programma te blijven volgen komen we nu uit in de - routine VULSCHERM, die het hele scherm vult met blokjes. - Alvorens ik de werking van VULSCHERM uit de doeken doe is - het nodig iets meer te praten op de opslag van de gegevens - over de mijnen. - - MAAR HELAAS DOEN WE DAT PAS DE VOLGENDE KEER! TOT DAN! - - Ruud Gelissen diff --git a/Future Disk/19/Moonblaster Music Cursus 2.md b/Future Disk/19/Moonblaster Music Cursus 2.md deleted file mode 100644 index 29a53f0..0000000 --- a/Future Disk/19/Moonblaster Music Cursus 2.md +++ /dev/null @@ -1,90 +0,0 @@ - MOONBLASTER CURSUS (2) - - - - Zoals iedereen (is d'r wel een hond die dit leest?)(NvdR: ja, - ikke!) de vorige keer al heeft kunnen lezen, zou ik deze keer - de drums bespreken. Dus niet; wegens tijdsgebrek ben ik er - niet aan toe gekomen, zelfs de muziek van deze FD is niet - meer dan minimaal.... Zo zie je maar weer, het leven van een - FD-redactielid gaat niet over rozen. Om de musiccorner toch - te kunnen vullen (en omdat ik toch nog een opmerking kreeg - dat ik de accoorden niet op de beste manier had uitgelegd, - maar daarover straks meer) ga ik het alweer hebben over de - accoorden. Degene die nu met de slimme (?) opmerking komt in - de geest van "Hee, dit lijkt de muziekcursus op de GPD wel" - (dat was waarschijnlijk 1 persoon (ene S.B. uit W., een - nogal beruchte MSXer die iets met Econometrie ofzo aan het - doen is)) moet het dan maar overnemen (dan heb ik tenminste - de tijd om de muziek eindelijk eens goed te maken...). - - NOGMAALS DE ACCOORDEN - - Ik heb op de vorige aflevering van de cursus wel van ��n - (NvdR: waauw dat is veel) persoon commentaar gehad, namelijk - van Stefan Boer, het opperhoofd van de stam der reizende en - rijzende zonnen. - Hij beweerde dat het allemaal eenvoudiger kon, en zou mij - dus een tekst hierover sturen die ik tot op heden nog niet - ontvangen heb (ja, dit is inderdaad een hint!). - Omdat ik de helft niet meer zo goed weet moet ik het maar - ongeveer uit m'n hoofd stampen, dus het zal wel niet - helemaal kloppen. - - Stel je maar eens een klavier voor, en ga bij het - onderstaande uit van de witte toetsen. - Je kiest een beginnoot (bv. C), je slaat een toets over, en - neemt de daarop volgende toets (in ons voorbeeld dus de E). - Doe ditzelfde ook voor de laatste noot van het - (driestemmige) accoord (de G), en je krijgt het volgende - accoord: C E G - - Volgens Stefan werkt dit zo met alle witte toetsen. Als je - goed luistert zul je merken dat er steeds hetzelfde verschil - in toonhoogte inzit (gek h�?), en hiermee kun je dus, als je - op het gehoor afgaat, ook zo een accoord met de zwarte - toetsen maken. De andere variaties uit de vorige cursus - krijg je geloof ik door de hoogste noot van het accoord een - octaaf te verlagen. Meer kan ik er momenteel eigenlijk niet - over zeggen, het wachten is op de beloofde tekst. Ik kom er - hoogstwaarschijnlijk nog wel op terug..... - -SOMETHING COMPLETELY DIFFERENT - - Om dit deel toch vol te krijgen kan ik nog wel iets - vertellen over de OPL-4 van Yamaha. De mogelijkheden zijn al - eens beschreven door Tobias "shit for brains", en hier zal - ik dus ook niet meer op ingaan. - De produktie van de MoonSound is aardig in de war gelopen. - De chips van Yamaha werden pas half februari verstuurd, dus - op zich zou het niet al te lang meer moeten duren, ware het - niet dat er een verkeerd onderdeel is besteld, waardoor de - eerste �cht werkende MoonSounds pas op de beurs in Tilburg - geleverd worden. De volgende series MoonSound en Graphics - 9000 worden waarschijnlijk een paar tientjes duurder. - Overigens krijg je bij deze twee produkten wel al kabels - meegeleverd. - De MoonSound komt - als het even meezit - wel in een - cartridge te zitten, met de V9990 is dit niet het geval. - Deze insteekkaarten zijn te groot om met een behuizing in - een cartridgeslot te passen, en daarom kun je je Graphics - 9000 in een metalen kastje laten bouwen voor Fl. 35,- (Dit - lijkt wel een STER-spotje voor Sunrise...) - Van MoonSound kun je waarschijnlijk nog wel binnenkort een - bespreking op de FD lezen... - - I'M GONNA LEAVE YOU - - Dit was het voor deze keer, mijn tijd is beperkt, en mijn - werk juist niet. Voor de volgende keer hopelijk een betere - en langere aflevering, met waarschijnlijk het laatste deel - van de accoorden en als nieuwe onderwerpen de drums en de - bassline.... - Cya !! - - Jorrith "slaapkop" Schaap - Erasmusweg 7 - 9602 AB Hoogezand - - - Tel: 05980-27379 diff --git a/Future Disk/19/Pascal 8.md b/Future Disk/19/Pascal 8.md deleted file mode 100644 index d7e874c..0000000 --- a/Future Disk/19/Pascal 8.md +++ /dev/null @@ -1,382 +0,0 @@ - PASCAL (8) - - - ���� Hallie hallo, hier is Smael weer met zijn PASCAL cursus. - ���� Deel 8 deze keer (nog twee en dan is het alweer - ���� voorbij). In deel 8 gaan we dieper in op pointers. - ���� Vorige keer heb ik uitgelegd wat pointers zijn en wat je - ermee kunt. Nu is het dus tijd voor een groot voorbeeld. - Als voorbeeld neem ik een programma om namen en adressen op te - slaan (een soort database dus). Goed, daar gaat 'ie (wat - hebben we weer een plezier)!!(NvdR: ja nou) - - Het programma staat op de disk als 'PASCAL8.PAS'. De listing - vind je terug in deze tekst, maar alleen ter verduidelijking. - - De declaraties veronderstel ik bekend (moet je kunnen) en daar - ga ik dus niet verder op in. Wel staan ze hier even vermeld, - zodat je de rest van het programma begrijpt: - - PROGRAM Pascal8(Input,Output,Namen); - - CONST - Max = 30; - - TYPE - Wijs = ^Rij; - Rij = RECORD - Naam : String[Max]; - Adres : String[Max]; - Next : Wijs; - END; - - VAR - Namen : Text; - Keuze : integer; - Hoofd : Wijs; - Hulp : Wijs; - Aantal : integer; - - Ik ga dus verder met de eerste procedure, aangezien hier - misschien dingen zijn die je niet begrijpt. Als ik zo naar - deze procedure kijk, dan kom ik tot de ontdekking dat je - alleen het commando 'ClrScr' niet kent, maar dat de naam alles - duidelijk maakt. Let ook op hoe ik het probleem van de - toetsdruk oplos. De computer wacht totdat ik op de - toets heb geramd, daarvoor kun je dus alle letters inrammen - die je wil (ze zullen zelfs zichtbaar zijn op het scherm). - Niet erg netjes dus, maar dat kun JIJ verbeteren (gebruik de - functie 'KeyPressed'). Verder gesneden koek: - - PROCEDURE welkom; - - BEGIN (* welkom *) - clrscr; - writeln('Dit is een voorbeeldprogramma bij FD #19'); - writeln; - writeln('Dit programma maakt het mogelijk een'); - writeln('adressenbestand op te bouwen.'); - writeln('Het is een voorbeeld dat gebruik maakt'); - writeln('van pointers.'); - writeln; - writeln; - writeln('Enjoy !!'); - writeln; - writeln; - writeln; - write('Druk om verder te gaan.'); - readln; - END; (* welkom *) - - Ook deze procedure moet gesneden koek zijn (alleen maar wat - Writeln's en Readln's). Wederom kun je een en ander - verbeteren. Als je namelijk een verkeerde keuze maakt, dan - wordt op de volgende regel opnieuw naar je keuze gevraagd. - Maak je ongeveer 20 keer de verkeerde keuze, dan is het - keuzemenu niet meer te zien (uit het beeld geschoven) en dat - is niet zo netjes. Read it and weep : - - PROCEDURE menu(VAR keuze:integer); - - BEGIN (* menu *) - clrscr; - writeln('Je kunt kiezen uit :'); - writeln; - writeln('(1) Bestand inladen'); - writeln('(2) Persoon invoeren'); - writeln('(3) Overzicht personen'); - writeln('(4) Persoon verwijderen'); - writeln('(5) Bestand opslaan'); - writeln('(6) Stoppen'); - writeln; - writeln; - writeln; - keuze:=0; - REPEAT - write('Uw keuze : '); - readln(keuze); - UNTIL (keuze>=1) AND (keuze<=6); - END; (* menu *) - - Hier wordt het interessant. Er wordt een file ingelezen van - namen die ooit al eens zijn ingevoerd. Deze heb ik lekker - gemakkelijk gehouden. Vergelijk hem maar eens met de SAVE - procedure en je komt tot de ontdekking dat de namen omgekeerd - ingelezen worden. Wat bedoel ik? Als de namen in alfabetische - volgorde zijn weggeschreven (als voorbeeld), dan worden ze - anti-alfabetisch (dus net omgekeerd van Z naar A) ingelezen. - Let ook op de VAR (in de procedure-kop) bij Hoofd en Namen. - Bij Namen is het altijd verplicht (een file kan niet in het - geheugen gekopieerd worden), maar bij Hoofd zou ik het weg - kunnen laten. Of niet (een pointer kan in het geheugen - gekopieerd worden)? In dit geval niet!! - - Als er al ��n naam (of meerdere) ingevoerd waren, dan kon ik - het weglaten (moet de rest wel achteraan toegevoegd worden) - aangezien Hoofd dan niet meer hoeft te veranderen (let vooral - op de voorgaande opmerking). Nu wordt elke nieuwe naam vooraan - in de lijst bijgeschoven en dus veranderd Hoofd bij elke naam. - Conclusie : VAR kan niet weggelaten worden (anders ben je je - namen kwijt als je terugkeert naar het hoofdprogramma). - - Let ook op het gebruik van de EOF functie. Ik hou er rekening - mee dat een file verminkt is. Ik zou kunnen volstaan met de - EOF controle bij de WHILE-lus, maar als de file verminkt is, - dan gaat het fout bij het inlezen van het adres. Gevolg is een - crash van de computer en dus zijn al je gegevens weg. Let - hier op bij het programmeren van een grote toepassing. Let - tevens op de 'Close(Namen)' aan het einde van de procedure, - deze is geplaatst om problemen te voorkomen indien je na het - inlezen het programma be�indigd (er staat immers nog een file - open). Verder bekend (neem ik aan) : - - PROCEDURE Laden(VAR Hoofd:Wijs;VAR Namen:Text); - - VAR - Hulp : Wijs; - - BEGIN (* Laden *) - Assign(Namen,'adres.txt'); - Reset(Namen); - WHILE NOT EOF(Namen) DO - BEGIN - New(Hulp); - IF NOT EOF(Namen) THEN - Readln(Namen,Hulp^.Naam) - ELSE - Hulp^.Naam:=''; - IF NOT EOF(Namen) THEN - Readln(Namen,Hulp^.Adres) - ELSE - Hulp^.Adres:=''; - Hulp^.Next:=Hoofd; - Hoofd:=Hulp; - END; - Close(Namen); - END; (* Laden *) - - Ook deze procedure moet geen echte problemen opleveren (zeker - niet als je de vorige procedure begrepen hebt). Hier worden - namen toegevoegd aan de lijst (wederom vooraan). Ik houd er - rekening mee dat de gebruiker gekke dingen doet, vandaar de - dubbele controle op het invoeren van een lege regel. Let ook - op de twee Dispose opdrachten op het einde van de procedure!! - Again, read it and weep : - - PROCEDURE Plus(VAR Hoofd:Wijs); - - VAR - Hulp : Wijs; - - BEGIN (* Plus *) - New(Hulp); - ClrScr; - Writeln('Toevoegen van naam aan lijst'); - Writeln; - Writeln; - Writeln('Geef naam en adres (RETURN is stoppen).'); - Writeln; - Write('Geef naam : '); - Readln(Hulp^.Naam); - IF Hulp^.Naam<>'' THEN - BEGIN - Write('Geef adres : '); - Readln(Hulp^.Adres); - IF Hulp^.Adres<>'' THEN - BEGIN - Hulp^.Next:=Hoofd; - Hoofd:=Hulp; - END - ELSE - Dispose(hulp); - END - ELSE - Dispose(Hulp); - END; (* Plus *) - - Aan deze procedure maak ik geen woorden vuil (buiten het feit - dat ik je wijs op het handige gebruik van de MOD functie bij - de REPEAT-UNTIL): - - PROCEDURE Print(Hoofd:Wijs); - - VAR - Teller : integer; - Hulp : Wijs; - - BEGIN - Hulp:=Hoofd; - Teller:=0; - REPEAT - ClrScr; - REPEAT - IF Hulp<>NIL THEN - BEGIN - Writeln(Hulp^.Naam); - Writeln(Hulp^.Adres); - Hulp:=Hulp^.Next; - END - ELSE - BEGIN - Writeln; - Writeln; - END; - Writeln; - Teller:=Teller+1; - UNTIL (Teller MOD 7)=0; - Write('Druk om verder te gaan.'); - Readln; - UNTIL Hulp=NIL; - END; (* Print *) - - Dit is natuurlijk de meest interessante procedure. Je zou hem - nu echter (na het lezen van Laden en Plus) zo goed als moeten - kunnen dromen. Nee, dat is maar een grapje(NvdR: haha). - Zelfs ik heb moeten denken hoe je dit gemakkelijk en snel - zou kunnen oplossen. Door een truukje gebruik ik maar twee - hulppointers in plaats van drie (ik gebruik de Next van - Hulp1 omdat die toch niet wordt gebruikt). Wat bij dit - soort procedures lastig is zijn niet de normale gevallen - (een naam middenin de lijst verwijderen), maar de bijzondere - gevallen (een naam in het begin of een naam op het einde - verwijderen). Probeer dit ook altijd goed uit als je zoiets - maakt, zodat je niet voor verassingen komt te staan. - Enjoy: - - PROCEDURE Min(VAR Hoofd:Wijs); - - VAR - Hulp1 : Wijs; - Hulp2 : Wijs; - - BEGIN (* Min *) - New(Hulp1); - ClrScr; - Writeln('Verwijderen van naam uit de lijst'); - Writeln; - Writeln; - Writeln('Geef naam (RETURN is stoppen)'); - Writeln; - Write('Geef naam : '); - Readln(Hulp1^.Naam); - IF Hulp1^.Naam<>'' THEN - BEGIN - Hulp2:=Hoofd; - IF Hoofd^.Naam=Hulp1^.Naam THEN - BEGIN - Hoofd:=Hoofd^.Next; - Dispose(Hulp2); - END - ELSE - BEGIN - WHILE Hulp2<>NIL DO - IF Hulp2^.Naam<>Hulp1^.Naam THEN - BEGIN - Hulp1^.Next:=Hulp2; - Hulp2:=Hulp2^.Next; - END - ELSE - BEGIN - Hulp1^.Next^.Next:=Hulp2^.Next; - Dispose(Hulp2); - Hulp2:=NIL; - END; - END; - END; - Dispose(Hulp1); - END; (* Min *) - - Tja, moet ik dit nog bespreken? Dacht het niet : - - PROCEDURE Saven(Hoofd:Wijs;VAR Namen:Text); - - VAR - Hulp : Wijs; - - BEGIN (* Saven *) - Assign(Namen,'adres.txt'); - Hulp:=Hoofd; - Rewrite(Namen); - WHILE Hulp<>NIL DO - BEGIN - Writeln(Namen,Hulp^.Naam); - Writeln(Namen,Hulp^.Adres); - Hulp:=Hulp^.Next; - END; - Close(Namen); - END; (* Saven *) - - Hier wordt natuurlijk alles samengevoegd, maar dat het je al - begrepen: - - BEGIN (* HOOFDPROGRAMMA *) - New(Hoofd); - Hoofd:=NIL; - welkom; - REPEAT - menu(keuze); - CASE Keuze OF - 1 : Laden(Hoofd,Namen); - 2 : Plus(Hoofd); - 3 : Print(Hoofd); - 4 : Min(Hoofd); - 5 : Saven(Hoofd,Namen); - END; - UNTIL keuze=6; - Hulp:=Hoofd; - WHILE Hoofd<>NIL DO - BEGIN - Hoofd:=Hoofd^.Next; - Dispose(Hulp); - Hulp:=Hoofd; - END; - END. (* HOOFDPROGRAMMA *) - - Dat was het. Weinig commentaar van mij dit keer, maar dat komt - omdat je dit zelf moet uitzoeken. Het programma werkt (ik heb - het uitvoerig getest) en dus kun je hier kijken hoe het moet. - Wat je moet doen om zelf meer te leren is het programma - aanpassen (daar heb ik het voor gemaakt). Dit programma bevat - alleen maar de namen en adressen (dat adres is niet compleet) - en moet dus eigenlijk uitgebreid worden met postcode, - woonplaats en telefoonnummer. Vandaar de volgende opdrachten: - - (1) Verbeter de invoerroutines, zodat een en ander mooier - uitziet als er een fout wordt gemaakt. - (2) Breid het programma uit, zodat ook de postcode, - woonplaats en het telefoonnummer van de betrokkene - ingevoerd en bewaard kan worden. - (3) Sorteer de gegevens alfabetisch (Tip : maak gebruik van - een bubblesort algoritme, dat is het gemakkelijkst bij - pointers). - - Smael, wat is bubblesort? Bubblesort is een sorteerroutine. - Hoe werkt dat? Als volgt : - (1) X <- 1 - (2) Vergelijk element X en X+1 met elkaar - (3) ALS element X+1 < element X DAN - wissel element X en element X+1 - (4) X <- X+1 - (5) ALS nog elementen DAN - ga naar stap 2 - (6) ALS gewisseld (tijdens ��n doorgang) DAN - ga naar stap 1 - En gesorteerd is die hap. - - Bubblesort werkt dus met doorgangen. Per doorgang zorg je - ervoor dat minimaal 1 element op de goede plaats komt (je - schuift dat element telkens voor je uit). Na ��n doorgang heb - je dus alle elementen minimaal ��n maal bekeken. Zolang je dus - wisselt (al is het maar ��n keer per doorgang) ben je nog niet - klaar met sorteren. Dit lijkt niet effici�nt, maar is het wel - (bubblesort is ongeveer 5 keer sneller dan de ouderwetse - sorteermethode met de twee FOR-NEXT loops) en daarbij is het - ook nog eens het gemakkelijkst bij pointers (hoe wil je dat - met twee FOR-NEXT loops oplossen?). - - Zo, dat was het. Tot de volgende keer, dan gaan we het hebben - over recursie (en dat is pas ECHT leuk). Groetjes, - - Jeroen 'FD^.Next^.Nummer:=20' Smael - - C YA @!! diff --git a/Future Disk/20/Data compressie 4.md b/Future Disk/20/Data compressie 4.md deleted file mode 100644 index 462aacc..0000000 --- a/Future Disk/20/Data compressie 4.md +++ /dev/null @@ -1,29 +0,0 @@ ---- Data Compressie 4 --- - - ���� - ���� - ���� - ���� - - - - Hoi, nadat ik vorige keer in verband met Tilburg geen kans - gezien had om nog een aflevering te maken zal ik dat proberen - nu goed te maken. Vorige keer beloofde ik dat we de methode - die ik daar beschreef in code zouden gaan omzetten. - - Nou, dat is gebeurd, maar omdat ik maar weinig tijd - heb(NvdR: smoesjes, eikel), is enkel de listing op deze disk - geplaatst, van een compleet werkende in en uitpakker onder - DOS. - - De listing staat onder de naam "RUNLEN.GEN" op de schijf. - Die is te assembleren met GEN80. In Wbass2 inladen kan ook, - maar dan zul je eerst alle tab's moeten laten vervangen door - spaties (inconsequentie van Wbass2). - - Veel plezier ermee en volgende keer volgt de uitleg bij de - listing. - - - Jan-Willem van Helden diff --git a/Future Disk/20/Moonblaster Music Cursus 3.md b/Future Disk/20/Moonblaster Music Cursus 3.md deleted file mode 100644 index e700d14..0000000 --- a/Future Disk/20/Moonblaster Music Cursus 3.md +++ /dev/null @@ -1,158 +0,0 @@ - MOONBLASTER CURSUS(3) - - - Jaahhh, daar is 'ie alweer. Het derde deel van de bij - jullie zoooo favoriete MoonBlaster cursus. De enige - sectoren op de FutureDisk die helemaal kapot gelezen - worden, de enige tekst die je printer laat doorbranden, - de enige die....(NvdR: de enige tekst die je nekvel - rechtop laat staan als je al die taalfouten eruit moet - halen!) - - Ahum, ik ben weer eens goed op dreef, ik heb hier totaal - geen zin in, mijn inspiratie is verdwenen (heb ik die - eigenlijk ooit wel gehad?) en aan deze cursus heeft alleen - Sunrise iets, omdat dit in hun ogen de enige cursus op de FD - is die het verdient om afgekraakt te worden. Maar goed, om - effe back to the point te komen, de vorige keer had ik - nogmaals de accoorden besproken. Ik zou hier nog een tekst - over ontvangen van dhr. Boer, aangezien ik alles de - vorige keer uit m'n hoofd moest doen (goed h�?). Deze tekst - heb ik nog steeds niet ontvangen, en ik ga er vanuit dat die - ook niet meer komt(NvdR: wat kinderachtig). Verder was er - niemand van betekenis met commentaar, dus ga ik gewoon verder - met het volgende onderdeel. Omdat ik nu ook eindelijk in - het bezit ben van een OPL-4 zal ik ook regelmatig verwijzen - naar dit Japanse muziekwondertje. Als je mazzel hebt kun je - zelfs de drumvoorbeelden uit deze cursus nog voor OPL-4 op - deze disk vinden...(ALLE MUZIEK VOOR OPL-4 STAAT INGEPAKT OP - DE DISK ONDER DE NAAM OPL4.PMA ... UITPAKKEN DUS DIE HANDEL - MET PMEXT.COM) - - MY FIRST SONY DRUMCOMPUTER - - Een zeer belangrijk deel in een MSX-muziekstuk wordt - ingenomen door de drums. Bij erg rustige nummers kun je het - soms ook nog achterwege laten, maar vaak zijn de drums toch - een vereiste. Als je nog maar net begonnen bent met je te - verdiepen in MoonBlaster, dan is het misschien verstandig om - een nummer altijd te beginnen met de drums, aangezien dit je - heel gemakkelijk helpt om ritme te houden. Voor de bezitters - van een MuziekModule allereerst nog een kleine tip: als je - meerdere drumkits gebruikt is het verstandig om voor ieder - drumgeluid toch hetzelfde drumnummer te gebruiken. - Bijvoorbeeld dat nummer 1 steeds een bassdrum is. Dit werkt - in de praktijk een stuk gemakkelijker. - Nog een tip voor OPL-4: als je zoveel sample-kanalen hebt, - ga je natuurlijk niet meer met de drums zitten klooien. Het - is echt van harte aan te bevelen dat je voor de drums - meerdere kanalen gebruikt. Met drie drum-kanalen kun je al - hele mooie dingen doen! - - EN NU? - - En dan nu de eigenlijke uitleg. Je hebt in MoonBlaster 2 - mogelijkheden wat betreft de maat van het muziekstuk. Dit - zijn namelijk een vierkwartsmaat (4/4); dit is gewoon ��n - hele pattern. Ook een driekwartsmaat (3/4) is mogelijk, dit - doe je door op elke pattern op de 12 (kan ook 11 zijn, ik - heb het niet gecontroleerd) stap een ENdOfPage (ENDOP) te - zetten. Ik ga nu uit van een vierkwartsmaat, aangezien die - het meeste gebruikt wordt. Als je dit eenmaal onder, boven - of tussen de knie hebt, dan lukt de 3/4-maat waarschijnlijk - ook wel (zie ook MDDRUM04.MBM). Op deze FD is trouwens ook - een muziekje in 3/4 maat geschreven, laad FUTURE01.MBM maar - eens in... Voor een heel erg standaardritme (zie ook - MBDRUM01.MBM op de disk) kun je het beste bovenaan de - pattern beginnen met een bassdrum. Op de FM-Pac voer je dit - in door op het drumkanaal te gaan staan en op "1" te drukken. - Met de MuziekModule hangt het er vanaf waar je de bassdrum - hebt staan, maar meestal zal dit ook de "1" zijn. Vervolgens - sla je ��n stap over en zet je op de plaats waar je nu staat - een hihat neer. Daarna sla je alweer een plaats over en zet - je een snaredrum neer, waarna je weer een plaats overslaat en - een hihat plaatst. Let er bij de OPL-4 wel op dat je - GM-Percussion geselecteerd hebt. Je krijgt dus het volgende - idee (dit is van links naar rechts omdat 't anders zoveel - ruimte inneemt): - - STEP: 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 - DRUM: 1 - 3 - 2 - 3 - 1 - 3 - 2 - 3 - - - (voor OPL-4:) - - STEP: 01 02 03 04 05 06 07 08 - DRUM: C 4 F#4 D 4 F#4 - - (Hier staat slechts de helft, om het overzichtelijk te - houden. Dit kun je natuurlijk eindeloos blijven herhalen). - - Nu klinkt het meestal mooier als je hier wat variaties in - aanbrengt, zoals je kunt zien in de file MBDRUM02.MBM en - MBDRUM03.MBM. Let er echter wel steeds op dat je maar beter - (in 't begin) drie (lege) posities tussen de bassdrum en de - snaredrum houdt. Later kun je dit altijd wel veranderen, en - je zult zien dat dit opvallende resultaten kan opleveren. - Mocht je overigens niet weten wat een bassdrum of een snare- - drum is, kijk dan naar het onderstaande lijstje: - - DRUM: MSX-Music (FM-Pac) MSX-Audio (MuziekModule) - - Bassdrum Drumnummer 1 Drumnummer 1 - Snaredrum Drumnummer 2 Drumnummer 2 - Hihat (closed) Drumnummer 3 Drumnummer 3 - Cymbal Drumnummer 4 Drumnummer 4 - Tom Drumnummer 5 Drumnummer 5 - Hihat (open) ------------ Drumnummer 6 - - OPL-4 bezitters kunnen dit lijstje wel vergeten, aangezien - alle drums al op de achterzijde van de handleiding staan. - - Bij het bovenstaande lijstje ga ik van een aantal dingen - uit: - - - Voor de MuziekModule heb je de drumkit FUTURKIT.MBK - ingeladen, waarna je ze kunt beluisteren in 't samplemenu - (F3). - - Voor FM-Pac ga ik uit van de drums die je hebt als je MB - opstart. Je kunt nu de drums beluisteren door in het - FM-drummenu (F8) te kiezen voor "Edit drumfrequency", - waarna je de drums kunt afspelen met F1 t/m F5. - - Let er wel op dat Fm-drums meestal mooier klinken als je - meerdere geluiden tegelijk gebruikt. Ook kunnen de PSG drums - een uitkomst bieden... - Voor de volledigheid heb ik ook nog een ritme gemaakt in de - 3/4 maat (zie MBDRUM04.MBM). - - MUSICAL CREATURES - - Het is mijn bedoeling om voor deze cursus ��n of twee - nummers op te bouwen met behulp van deze cursus. Zo kun je - op deze disk al twee voorbeelden beluisteren waar de drums - en de accoorden al gebruikt worden.... Misschien... want - echt veel tijd heb ik niet meer. Kijk maar op de disk! - Overigens, er staan voor de gelukkige bezitters van een - OPL-4 ook nog een aantal songs op.... Voor de volgende keer - probeer ik mijn leven te beteren en jullie plat te gooien - met muziek(achtige) zooi. Ook zal ik meer aandacht aan de - OPL-4 besteden, maar dat merk je dan wel... - - I QUIT WITH THIS BULLSHIT - - Ja mensen, jullie hebben het goed gelezen. Ik kap er voor - deze keer maar mee, 'k heb er geen zin meer in. Je kunt - zoals gewoonlijk op- of aanmerkingen sturen naar het - redactieadres, of desnoods (tweede keuze) doorgeven aan - mij. - -Sayonara! - - Jorrith "I don't like this" Schaap - - - Jorrith Schaap - Erasmusweg 7 - 9602 AB Hoogezand - Nederland - diff --git a/Future Disk/20/Muizen in BASIC.md b/Future Disk/20/Muizen in BASIC.md deleted file mode 100644 index e8ab26e..0000000 --- a/Future Disk/20/Muizen in BASIC.md +++ /dev/null @@ -1,101 +0,0 @@ - - MUIZEN IN BASIC - - ���� - ���� - ���� - ���� - - Wederom een tekstje voor de wat minder gevorderden. Dus al - die oude rotten die eigenlijk alles al weten van Basic - moeten maar gewoon ML gaan leren of zo... De muis... men - plugt 'm in poort 1 of 2, men rammelt een beetje met ons - electronische knaag diertje en zie daar, de muiscursor - huppelt vrolijk 't scherm door. Om deze schokkende gebeur- - tenis te achterhalen gebeurt er nog al 't een en ander in - ons MSXje. De technische uitleg wou ik dan maar achterwege - laten maar het hoe en wat betreffende 't uitlezen in basic - wou ik wel even behandelen... - -PAD - Dat is 't commando waar 't allemaal mee dient te gebeuren... - Pad wordt voornamelijk gebruikt om de status van de muis en - de trackball uit te lezen. PHILIPS heeft echter destijds - ooit ook nog eens van die shit zoals tekentableuas en - lichtpennen uitgebracht die ook met pad werken. - - In de praktijk zal het uitlezen ook nog wel mee vallen, maar - het checken of er wel een muis is aangesloten valt over 't - algemeen tegen. Dat valt namelijk niet te checken op een MSX. - Er is echter wel een truukje dat kan worden gebruikt, maar dat - is niet echt netjes(NvdR: net of dat iemand boeit?!). - - De syntaxis - - A=PAD(X) - De waarde van PAD komt hierdoor in A terecht waarbij in X - de specifieke gegevens voor PAD dienen te worden opgegeven. - 12 of 16 Zal altijd -1 geven maar MOET worden opgevraagd - voordat X en Y worden bepaald. - 13 of 17 De verandering op de X-as. - 14 of 18 De verandering op de Y-as. - - Het linker getal is steeds voor poort 1, het rechter voor de - tweede poort. De beste manier om dan de muis coordinaten bij - te houden is gewoon steeds PAD(13) by het X-coordinaat op te - tellen en PAD(14) bij het Y-coordinaat op te tellen. - PAD(12) heeft dus geen functie maar moet wel voor 't - opvragen van PAD(13) en PAD(14) worden bepaald. - Een voorbeeld: - - 10 SCREEN5:X=127:Y=105 - 20 DUMMY=PAD(12):X=X+PAD(13):Y=Y+PAD(14) - 30 IFX<0THENX=0:ELSEIFX>255THENX=255 - 40 IFY<0THENY=0:ELSEIFY>211THENY=211 - 50 PSET(X,Y),15:GOTO20 - - Door het bewegen van de muis kunnen we nu keurig een lijntje - trekken over 't scherm. Maar als we nou ook af en toe geen - lijnje willen trekken? Goed, gaan we weer: - - 10 SCREEN5:X=127:Y=105 - 20 DUMMY=PAD(12):X=X+PAD(13):Y=Y+PAD(14) - 30 IFX<0THENX=0:ELSEIFX>255THENX=255 - 40 IFY<0THENY=0:ELSEIFY>211THENY=211 - 50 IFSTRIG(1)THENPSET(X,Y),15:GOTO20:ELSEGOTO20 - - Nu kunnen we de muis vrijelijk door 't scherm laten bewegen - zonder dat we een lijntje trekken. Pas als we trig1 inhouden - zal er een lijntje worden getrokken. Maar nu weten we dus - niet waar de muiscursor is als we niet aan 't tekenen zijn. - Hiervoor voegen we weer twee regels toe: - - 15 SPRITE$(1)=CHR$(&H80) - 45 PUTSPRITE 0,(X,Y),14,1 - - Nu zal er op de plek van de muis-coordinaten ook echt een - muiscursor verschijnen; nou ja, een grijs stipje. - Maar Tobias zou Tobias niet zijn als ie niet nog een - netelig probleem kon bedenken. Juist ja, misschien zit de - muis wel in poort 2. - - 05 X=0:FORL=0TO25:DUMMY=PAD(12):X=X+PAD(13):NEXTL:IFX>-5 - ANDX<5THENMO=12:TR=1 - 10 X=0:FORL=0TO25:DUMMY=PAD(16):X=X+PAD(17):NEXTL:IFX>-5 - ANDX<5THENMO=16:TR=3 - 15 SCREEN5:X=127:Y=105:SPRITE$(1)=CHR$(&H80) - 20 D=PAD(MO):X=X+PAD(MO+1):Y=Y+PAD(MO+2) - 30 IFX<0THENX=0:ELSEIFX>255THENX=255 - 40 IFY<0THENY=0:ELSEIFY>211THENY=211 - 50 PUTSPRITE0,(X,Y),14,1 - 60 IFSTIRG(TR)THENPSET(X,Y),15:GOTO20:ELSEGOTO20 - - Nu hebben we eindelijk een routine die met de muis in elke - poort een muis cursor op 't scherm zet en bij een knop op - de linker vuurknop een punt zet. - - Wauw! fantastisch, heb ik weer en half uur zitten typen en - weer geen hond die 't leest. A well, that FutureDisk life! - (NvdR: what life?) - -Keizer... diff --git a/Future Disk/20/Turbo-R BASIC.md b/Future Disk/20/Turbo-R BASIC.md deleted file mode 100644 index a9fc0e5..0000000 --- a/Future Disk/20/Turbo-R BASIC.md +++ /dev/null @@ -1,177 +0,0 @@ - THIS TEXT WAS NOT SPONSORED BY WEBBER... - - De turbo en basic, een prima combinatie. - Veel mensen hebben de heilzame invloed van de R800 in hun - Turbo-R wel gemerkt, vooral in basic, wat vroeger nog in ML - moest kan nou ook in basic, met de R800 aan, dat wel. - - Toch weten veel mensen niet hoe alles nu zo'n beetje wordt - aangestuurd, en dat is jammer. Want zelfs de dingen die in - eerste instantie niet zo nuttig lijken zijn toch leuk om aan - te sturen, en dat kan zelfs in basic.. Lees, en ontdek. - -DE LEDJES - - Op de Turbo zitten een aantal ledjes, 7 om precies te zijn. 't - is altijd leuk om hiermee van die Knight Rider effectjes uit - te halen, vandaar even de aansturing. De Caps en de Kana leds - zijn neem ik aan bekend. De power led en de FDD led kun je in - basic niets mee, hoewel je, als je heel moeilijk doet, in ML - de FDD led meen ik WEL aan kan zetten. Blijven er drie leds - over, de RENSHA led, de R800 led en de PAUSE led. De RENSHA - turbo schakeling valt helaas niets mee te doen op ons MSX-je. - Dit hele ding is hardwarematig waarbij er vrijwel geen - software-matige truukjes worden uitgehaald. Er kan met de - potmeter worden ingesteld hoe lang de blokpuls die - gegenereerd wordt moet zijn en vervolgens word deze geORd - met PSG register 14 bit 4 en de 0de bit van rij8 van de - Toetsenbord matrix. Zie hiervoor vorige FD. Dit gebeurt - dus eigenlijk allemaal hardware-matig en je hebt hier dus - niets aan. Zou je de lengte van een puls willen meten moet - er nog eerst op een trig A worden gedrukt. Blijven de TURBO - en PAUSE led over: - - TURBO led: OUT &HA7,&B00000001 - PAUSE led: OUT &HA7,&B00000001 - - Waarbij de 1 natuurlijk aan is op de juiste plaats. Alle - combinaties met bit 0 en 7 zijn natuurlijk mogelijk. Op de - disk staat nog wel even en replayertje dat even leuk laat - zien hoe de ledjes bijvoorbeeld kunnen worden gebruikt. - -DE FIRM-SOFTWARE-SWITCH. - - In beide turbo's zit een aanzienlijke hoeveelhed zogenaamde - FIRM-SOFTWARE. VIEW op de GT en HIRO op de ST. Deze software - staat op ROM en is dmv de schakelaar op de kast aan en uit te - schakelen. Het leuke is dat de stand van deze schakelaar in - basic is uit te lezen. Dit is op zich wel grappig om ook - eens in eigen programmatjes te gebruiken zoals je ook in - mijn replayertje kan zien. In $E4 wordt een 5 gezet om de - swith uit te lezen waarna de INP waarde nog even met 64 - geANDd moet worden om 't uiteindelijke resultaat te - krijgen. - - 10 OUT &HE4,5 : SW=INP (&HE5) AND 64 - 20 IF A=64 THEN PRINT "ON" ELSE PRINT "OFF" - -CANCEL & CONFIRM TOETSEN - - De Turbo's hebben ook nog een drietal extra toetsen. De, om ze - maar een naam de geven, Cancel en Confirm toetsen en dus de - Pauze toets. De pauze toets zat al eerder op 2+n maar toen was - het nog een hardware matige schakelaar. Bij de Turbo is de - pauze toets echter software matig en is naar mijn mening nu - pas een echte toets. Met de pauze toets kun je echter niets in - basic omdat onder basic de interrupt normaal gesproken altijd - aan is en dan dus de computer ook echt gaat pauzeren. In MC is - het echter wel degelijk mogelijk om met alle Turbo-toetsen te - spelen. Dan blijven dus de CANCEL en CONFIRM toetsen, naast de - spatiebalk, over. Deze zitten gewoon in de toetsenbord buffer - en wel op resp bit 3 en bit 1 van rij 11. Zie over details van - toetsenbord uitlezing de vorige FD. Om deze toetsen uit te - lezen brijg je dus het volgende programmaatje. - - OOPS, toen bleek dit inderdaad rij 11 te zijn, en of die ook - echt op adres '11' staat weet ik niet, nou goed, een gokje dan - maar hoe 't zou kunnen werken in BASIC, of dit zo is weet - ik niet. - - 10 IF (PEEK(&HFBF0)AND&B00000001)=0 THEN PRINT "CONFIRM" - 20 IF (PEEK(&HFBF0)AND&B00000100)=0 THEN PRINT "CANCEL" - 30 CLS:GOTO10 - - Anders kan 't altijd nog in ML met: - - GETKEY: LD A,11 - CALL $0141 - BIT 1,A - JP Z,CONFIR - BIT 3,A - JP Z,CANCEL - JP GETKEY - -DE PCM-SAMPLER - - En dan als laatste nog de PCM waar ik niet al te veel tijd - aan wil besteden omdat die eigenlijk al gesneden koek is - voor de meesten. - De syntaxis: - - CALL PCMREC (@,,,[SV],[RL],[S]) - CALL PCMPLAY (@,,,[S]) - - SA: Start Adres, &H0000 - &HFFFF - EA: Eind Adres, &H0000 - &HFFFF - FR: Frequentie, 0 - 3 - - SV: Start Volume, reageert bij bepaald volume. - RL: Run Length, soort runlength, telt aantal 'nullen' - S: opslag in VRAM in plaats van RAM. - - Die runlength wil ik nog wel even op terug komen. Die is - namelijk niet wat je zou vermoeden. Als de computer - namelijk een bepaalde tijd 'stilte' registreert dan treedt, - indien aangezet, deze optie in werking. De tijd die de - stilte duurt wordt opgeslagen i.p.v de data die deze stilte - beschrijft. Nog even een voorbeeld programmaatje. - - 05 ' SAMPLE.BAS - 10 IF PEEK(&HF677)=&HC0 THEN GOTO 30 - 20 POKE &HF677,&HC0 : POKE &HC000,0 : RUN "SAMPLE.BAS" - 30 FORP=2TO15:OUT &HFE,P:_PCMREC (@&H8000,&HBFFF,0):NEXTP - 40 FORP=2TO15:OUT &HFE,P:_PCMPLAY(@&H8000,&HBFFF,0):NEXTP - 50 OUT &HFE,1 : POKE &HF677,&H80 : POKE &H8000,0 : NEW - - En zie daar, en bere lange sample. Nou dat was 't dan wel - voor deze keer want ik ben 't nu wel zat, see ya'll... - -Keizer - - Wat ben ik toch ook een lekker slim joch, heb ik 't over de - Turbo-R, vergeet ik 't belangrijkste, de R800. Deze is he- - laas niet in BASIC met een call of zo aan te zetten, dit moet - echt in machinetaal gebeuren. Door echter een zestal getallen - in het geheugen te poken wordt dit probleem opgelost... - - 10 FOR L=0 TO 5: READ V: POKE &HC000+L,V: NEXT L - 20 POKE &HC001,&B10000000 'Z 80 MODE - 30 POKE &HC001,&B10000001 'R800 MODE - 40 POKE &HC001,&B10000010 'DRAM MODE - 50 DEFUSR=&HC000:A=USR(0): DATA &H3E,&H00,&HCD,&H80,&H01,&HC9 - - Nou, als 't goed is werkt dit wel dus dan is deze text nu echt - aan z'n einde gekomen. Nog even melden dat de DRAM mode dus de - laatste 64kB van je geheugen afsnoept, maar deze is dan ook 'n - stuk sneller dan de R800 modus, als je veel BIOS routines gaat - gebruikem tenminste... Maar dat zal in BASIC vaak wel het - geval zijn.... - - Groeten, Keizer... - - En dit werkt natuurlijk niet nu ik er over na denk... - Die routine zit natuurlijk in de SUB-ROM en niet in de - Main Rom... - Een nieuwe routine dus.... - - 10 FOR L=0 TO 6:READ V:POKE &HC000+L,V:NEXT L:DEFUSR=&HC000 - 20 A=&B10000000 'Z 80 MODE - 30 A=&B10000001 'R800 MODE - 40 A=&B10000010 'DRAM MODE - 50 Z=USR(A): DATA &HDD,&H21,&H80,&H01,&HCD,&H5F,&H01,&HC9 - - Hierbij mag je de eerste 1 weglaten als je niet wilt dat de - led mee veranderd. Well, now it should work.... - - Keizer. - - En daar ben ik weer... -ik zal ook eens een tekst in een keer - typen- En weer eens met nieuws omdat ik nooit ene flikker uit - voer. Nou ja, bijna nooit. Door het poker spelletje van deze - keer heb ik weer eens geen tijd gehad om het beloofde - programmaatje te maken dus U kunt vrolijk vloeken en - schelden op het nummer 046-374322, het nummer van de - hoofdredacteur...(NvdR: die U vervolgens doorstuurt naar de - crimineel in kwestie Dhr. T.K.K. Keizer. 05202-31343) - - Tobias Keizer. diff --git a/Future Disk/21/Call Kanji.md b/Future Disk/21/Call Kanji.md deleted file mode 100644 index 2783328..0000000 --- a/Future Disk/21/Call Kanji.md +++ /dev/null @@ -1,178 +0,0 @@ - Een aardige uitleg door de DHR KEIZER. Hoe typ ik het Japanse woord voor "schaamhaar" in zonder dat ik het zelf weet? - - -CALL KANJI?? - - ���� - ���� - ���� - ���� - - Yep, voor de 2-plussers -neen, dit zijn geen kleuters of - peuters- onder jullie wel. Iedereen kent dat _Kanji gedoe - wel, veel mensen weten echter niet dat dit meer dan wat - grotere lettertjes op kan leveren. - - Modi: - De Kanji mode op de 2+ kent weer een aantal verschillende - modi. Vier om precies te zijn. Het verschil zit hem vooral - in de letter-breedte en letter hoogte. De verschillen: - _KANJI0 ; 8*16, low res, non interlace. - _KANJI1 ; 6*16, low res, non interlace. - _KANJI2 ; 8*16, highres, interlace. - _KANJI3 ; 6*16, highres, interlace. - - De 8*16 en de 6*16 staan voor de pixel breedte/hoogte van de - ASCII karakters. Het normale font wordt namelijk uitgezet. In - plaats hiervan wordt er een speciaal karaktersetje door de Jis - rom ingeschakelt dat de normale ascii letters moet vervangen. - De JIS-Karaktes -zoals de Kanji-letters heten- zijn echter - altijd 16*16. De jis letters uit mode 0 & 1 en uit mode 2 & 3 - zijn dus verder gelijk. Het voordeel van deze schermen was dus - eigenlijk alleen voor de Japanners merkbaar. Ze konden immers - kanji op hun scherm krijgen die leesbaar zijn. Voor ons zijn - er echter ook voordelen. Zo is nu eindelijk dat gepiemel met - OPEN "GRP:" AS #1 afgelopen in een grafisch scherm. Staat de - kanji-driver aan, dan volstaat een PRINT gewoon. Tevens kunnen - commando's als locate en input na het aanroepen van de kanji - driver gewoon gebruikt worden in de grafische schermen. Maar - zelf vind ik bijvoorbeeld de karakters in KMODE2 een stuk - mooier dan die iele ascii lettertjes. Jammer is wel dat de - interlacing na lange type sessies gaat storen. - - Niet alles werkt: - Neen helaas niet, maar daar hebben de heren bij ASCII wel een - oplossing op gevonden. Zo zal het commando CLS domweg een - "Illegal function call" opleveren. Evenals COLOR= niet meer - toegestaan is. De oplossing hiervoor is vrij simpel. _CLS doet - het prima in een kanji scherm, terwijl _PALETTE de oplossing - blijkt te zijn voor het COLOR= probleem. Verder vind ik het - toch wel storend dat het niet mogelijk is om de gewenste kanji - op de gewenste X-Y positie te krijgen in een grafisch scherm. - De enige manier waarop dit mogelijk is, is door het gebruiken - van Jis-codes -die ik later in deze text nog bespreek- die vry - onhandig zijn en in feite nooit voorkomen. In grafische modi - ka dit erg lastig zijn daar er dus karakters zijn met verschil - lende breedtes. De 'standaard' gebruiker zal echter aan locate - genoeg hebben. - - Jis en Shift-Jis. - Om het grote aantal tekens -Kanji, Katakana en Hiragana- uit - de Japanse taal in een computer te krijgen was een nieuw en - beter systeem nodig. De ascii set gaf immers maar ruimte voor - 256 tekens min 32 tekens voor de schermaansturig. Voor de Jap- - anse taal bij lange na niet genoeg. Er moest dus een nieuw 2- - byte systeem worden ontworpen waarmee dus 65536 tekens kunnen - worden opgeslagen. Na een aantal lange druilerige zondag mid- - dagen was men er uit in Japan. De Jis standaard vond het licht - en alles ging veranderen. 65536 tekens zou zelfs voor de Chi- - nese taal genoeg zijn, maar goed... Vrijwel alle mogelijk Kan- - ji uit de Japanse taal werden in het Jis-systeem opgenomen, - evenals alle Katakana en Hiragana, met accenten en zonder. - Maar zelfs toen hadden de heren nog ruimte over. In de Jis2 - standaard staan dus, "alle" Kanji, Katakana, Hiragana, de - Europese schrift-tekens, het arabische numerieke stelsel, de - Griekse schrift-tekens, russisch, oud latijns, dubbele getal- - len, dubbele letters, alle! mogelijke leestekens uit alle wet- - telijk erkende talen(NvdR: ook Ijslands?), "alle" valuta- - symbolen, "alle" symbolen van maten en eenheden, tekeningen! - voor educatieve software, de nodige symbolen van - telefoontjes, vliegtuigen enz, afkortingen van bv TEL, FAX, - No. enz..... Te veel om op te noemen -en toch deed ik dat - net-. In de meeste 2+en en in de Turbo-R zitten zo wel de - JIS1 als de JIS2. In alle DOS2 cartridges zit de JIS1.. - In totaal zit er in de Turbo een dikke 256K aan Jis - lettertjes wat genoeg is voor 8192 karakters, waarvan er - zeker zo'n 7000 gebruikt worden. Om deze enorme hoeveelheid - aan karakters te kunnen gebruiken zijn er 2 aanstuur-codes - in gebruik. JIS en SHIFT-JIS. Het verschil tussen die 2 is - nogal vaag maar het komt er op neer dat JIS meer iets van - een adres weg heeft en SHIFT-JIS meer een logische code is. - Een shift-jis code begint altijd met een getal hoger dan - HEX 80 gevolgd door een ander getal hoger dan HEX 20. Hoe - dit bij Jis zit weet ik niet echt. - In de praktijk werkt men meestal met Shift-Jis en de lul die - Jis heeft bedacht mogen ze van mij dan ook morgen ophangen.... - -WERKING ONDER BASIC - - Onder Basic kan men ook de gewenste kanji of kana op 't - scherm krijgen, maar natuurlijk niet door met een toets- - combinatie te werk te gaan. Na een _KANJI2 kan men op CTRL- - SPACE drukken wat onder in 't scherm een command line - oplevert. Op de plaats die normaal door de functie toetsen - wordt ingenomen staat nu een 2 de cursor waar men kan gaan - typen. De bedoeling van het geheel is dat in "Romaji" -dit - is naam voor japans geschreven op een fonetische manier- - de gewenste kanji in typen, alle let ter gre pen worden - indien mogelijk vertaald naar Hiragana -de naam van het - Japanse fonetische lettergreepschrift- en als het woord nu - herkend wordt zal de bijbehorende Kanji op het scherm worden - gezet. Omdat het Japans echter veel homofonen kent kan men - met de spatie echter kiezen uit alle kanji met die - uitspraak, niet ideaal maar het is een oplossing. Probeer - maar eens "MORI" in te typen, het Japans voor boom/bos. - Na het typen van "MO" zal "MO" vervangen worden voor het - Hiragana teken voor de klank MO en na het typen van de - "RI" zal ook "RI" vervangen worden door het hiragana teken - voor de klank "RI", heeft overigens iets weg van een - handgeschreven "Y". - Drukt men nu op de spatie dan zullen de Hiragana tekens - "MO RI" worden vervangen door een Kanji, welke dit zal zijn - weet ik ook niet uit m'n hoofd maar uiteindelijk moet er - een teken op het scherm komen dat wel wat weg heeft van - 3 "*" sterretjes, twee onder, een boven. Als na - het drukken op de spatie -net zolang tot het teken in beeld - is dat men zoekt- het juiste teken is gevonden kan men met - return het teken op de plaats van de eerste cursor krijgen. - Verder is het ook mogelijk om in het Europese-font uit de - Jis2 rom te typen. Na een druk op F-1 zulllen alle tekens - in JIS letters op het scherm komen waardoor mooie lettertjes - te verkrijgen zijn. Na een druk op return komen deze - prachtige 16*16 Europese letters op de plek van de eerste - cursor. Nog een druk op F-1 en deze stand wordt weer uit - gezet. - -KATAKANA - - Verder is er ook het wat bekendere Katakana. Dit schrift - wordt door de Japanners gebruikt om Engelse woorden in - Japanse tekens te schrijven. De werkwijze is hetzelfde als - bij de Kanji alleen drukt men na het typen van het hele - woord op F-2 zodat alle hiragana tekens vertaald worden - naar katakana tekens. Lukraak weg typen kan echter niet. - Het Japans kent maar een paar klanken zodat de Engelse - woorden meestal zwaar verminkt naar katakana vertaald - moeten worden. Zo zal "FutureDisk" vertaald moeten worden met - "Pyu tya Di su ku". Zie aan 't eind van deze text de tabel - met alle katakana klanken. Om uit de commandline te komen - volstaat een tweede druk op CTRL-SPACE, overigens soms "pakt" - de computer die toetsdruk niet gelijk. Gewoon nog een keer - drukken... Om uit een Kanji scherm te komen is _ANK het - commando. - -DE KATAKANA KLANKEN: - - A I U E O BA BI BU BE BO < De "H"-klank met accent. - KA KI KU KE KO PA PI PU PE PO < idem. - SA SI SU SE SO DA DI DU DE DO < De "T"-klank met accent. - TA TI TU TE TO ZA ZI ZU ZE ZO < De "S"-klank met accent. - NA NI NU NE NO PYA PYU PYO< "PI" + "Y" klank. - HA HI HU HE HO TYA TYU TYO< "TI" + "Y" klank. - MA MI MU ME MO - YA YU YO - RA RI RU RE RO - WA NN - - Dit klopt niet helemaal, de meeste uitspraken verschillen wel - iets van wat hier staat maar over het algemeen is het - makkelijker om dit aan te houden... - - Dat was het dan wel voor deze keer, ik neem aan dat de - brievenschrijver van een aantal disks geleden tevreden is. - De 2-plus heb ik nu een paar keer achter elkaar behandeld - en ik denk dat ik maar stop met de 2+ en weer even op - MSX 2 overstap omdat we geloof ik niet zo gek veel 2+ leden - hebben. Nou dat was 't wel, dus... See ya! - -Keizer... diff --git a/Future Disk/21/MCode Special 2.md b/Future Disk/21/MCode Special 2.md deleted file mode 100644 index d1dd743..0000000 --- a/Future Disk/21/MCode Special 2.md +++ /dev/null @@ -1,202 +0,0 @@ - Ruud vervolgt deze speciale programmeercursus... - - - MCODE SPECIAL (2) - - We vervolgen waar we op FD #19 gebleven waren... - - Het DATAveld - - We hebben dus een veld van 16*13 blokjes, waaronder al dan - niet mijnen zitten. Wat moeten we nu precies van een blokje - weten: - - 1. Mijn of niet - 2. Al zichtbaar gemaakt of niet - 3. Op veilig gesteld of niet - 4. Aantal aangrenzende mijnen. - - De gegevens 1 t/m 3 zijn vragen, die met ja of nee beantwoord - kunnen worden: Per gegeven is 1 Bit genoeg (JA: Bit staat op 1; - Nee: Bit staat op 0). Het laatste gegeven is een getal tussen - de 0 en de 8: hiervoor zijn 4 bits nodig. - We hebben dus per veld genoeg aan 7 bits, dus zeker genoeg - aan 1 byte(8 bits). Om al onze gegevens te kunnen opslaan - wordt gebruik gemaakt van 16*13 bytes: het DATAveld - (label:DATA). Een byte in het DATAveld heeft de volgende - betekenis: - -bitnr. 7 6 5 4 3 2 1 0 - mijn zichtbaar vlag x aantal aangrenzende mijnen - - De bovenste nibble (4 bits) zijn de gegevens en de onderste - geeft het aantal aangrenzende mijnen aan. - De eerste byte in het DATAveld heeft betrekking op het - blokje linksboven in beeld op xco,yco:(0,0). - De tweede byte heeft betrekking op het blokje op - xco,yco:(16,0). De 16e byte heeft betrekking op het blokje - op xco,yco:(0,16) etc.. - - Om te kunnen laten testen of ons programma werkt vullen - we nu eerst een dataveld zelf met mijnen, zoals in - MINESW.GEN het geval is. - - -VULSCHERM (kopieren in MC) - - Deze routine vult het scherm aan de hand van het DATAveld - met de juiste blokjes. Het HL register is de Adrespointer: - deze geeft aan met welk adres in DATA gewerkt wordt. B is - een teller die telt hoeveel blokjes we gehad hebben. Telkens - als 1 blokje gedaan is worden zowel HL als B met 1 verhoogd. - De routine wordt herhaald tot B>16*13 geworden is: - het hele scherm is dan gevuld. - - - Voor het neerzetten van een blokje is de routine COPY - essentieel. Deze routine copieert een stuk uit het VRAM - (in ons geval een van de blokjes van Page 1) naar een - andere plaats in het VRAM, net als het basic commando COPY. - Net als bij SETPAL ga ik hier niet uitleggen hoe deze routine - precies werkt, maar vertel ik slechts wat je nodig hebt om - hem te gebruiken. In het HL regeister moet het adres staan - waar de gegevens staan die nodig zijn voor de COPY. In dit - geval is dit het adres BLOKDATA. Je ziet hier hieronder - hoe die gegevens eruit moeten zien. - - -BLOKDATA: ; gegevens voor het COPY commando -SX: DB 0,0 ; source xco (welke xco komt het - blokje vandaan) -SY: DB 0 ; source yco ( yco ) -SPAGE: DB 1 ; source page( pagina ) -DX: DB 0,0 ; destination xco - (welke xco moet het naar toe ) -DY: DB 0 ; yco -DPAGE: DB 0 ; page -LX: DB 16,0; lengte in x-richting -LY: DB 16 -OVERIGE: DB 0,0,0 -COMMANDO: DB #D0 ; plaats blokje m.b.v. snelle copy - -; p.s. vergelijk met in BASIC: -; COPY (SX,SY)-(SX+LX,SY+LY),SPAGE TO (DX,DY),DPAGE - - - Merk op dat voor de x-coordinaten 2 bytes gereserveerd zijn, - dit omdat een xco in screen 7 tussen de 0 en 512 ligt en dus - 2 bytes in beslag neemt. - Als screen 5 aanstaat staan er altijd nullen in de 2de byte - voor de xco. - - Omdat alle blokjes 16x16 groot zijn en alle gekopieerd worden - van Page 1(SOURCE YCO=0) naar Page 0, liggen veel gegevens - al vast. - Het kopieren van een blokje komt er nu nog op neer de - juiste SX,DX en DY in te vullen en dan m.b.v. - - LD HL,BLOKDATA - CALL COPY - - het eigenlijke kopieren uit te voeren. - - De VDP start na het geven van het COPY commando met het - kopieren, de Z-80 werkt echter gewoon door met zijn eigen - instructies! - De VDP is dus eigenlijk een soort co-prossesor. Pas hiermee - op: als het commando COPY wordt gegeven staat de COPY dus nog - niet klaar; dat kan soms onhandig zijn als je er zeker van - moet zijn dat een bepaalde COPY gebeurd is voordat je verder - gaat met de volgende Z-80 instructies (hier is dat niet het - geval). - Als je wilt wachten tot de VDP klaar is kun je de volgende - routine gebruiken. - -COPYREADY: LD A,2 - CALL VDPSTA ; lees statusregister 2 - RRA - JP C,COPYREADY ; de VDP is nog niet - klaar: wacht hier - RET ; klaar voor volgende copy. - - - Het invullen van de juiste SX betekent dat we moeten weten welk - symbool op deze plaats van het beeld staat m.a.w. we moeten in - het DATAveld kijken. - - Bit voor Bit wordt gekeken in het DATAveld m.b.v de volgende - routine: - -VULSCHERML: LD A,(HL) ; in A staan de gevgevens over - het blokje - BIT 5,A - JR NZ,VLAG - BIT 6,A - JR Z,ONZICHTBAAR ; maakt niet uit wat - eronder zit - BIT 7,A - JR NZ,MIJN - - AND %00001111 ; het blokjes is een getal - of leeg -GETAL: ADD A,A - ADD A,A - ADD A,A - ADD A,A ; *16 - LD (SX),A - JP SETDX - - De volgorde van het afgaan van de Bit's is niet willekeurig: - het is niet de bedoeling dat er een mijn neergezet wordt - terwijl het blokje nog niet eens zichtbaar was - Als geen van de bovenste Bits in de DATA aanstaat, moet er - een getal neergezet worden. - M.b.v. de AND %00001111 worden de bovenste Bit's van het - A-register op 0 gezet en de onderste niet verandert: in A - staat nu het getal dat aangeeft hoeveel mijnen er om het - blokje heen liggen. - Als het getal 0 is moet het blokje met SX=0 gekopieerd - worden. - Als het getal 1 is moet het blokje met SX=16 gekopieerd - worden. - Als het getal 2 is moet het blokje met SX=32 gekopieerd - worden. - Vandaar dat het getal met 16 vermenigvuldigd wordt om de SX - te krijgen. - - Wat er ook voor blokje afgedrukt wordt: uiteindelijk (als de - SX bepaald is) komt de MSX aan bij de volgende routine: - -SETDX: ; bereken aan de hand van B de destination xco en yco - LD A,B - AND %00001111 ; getal tussen 0 en 15 - ADD A,A - ADD A,A - ADD A,A - ADD A,A ; *16 - LD (DX),A - ; getal tussen 0..16..32..48..64....240 - LD A,B - AND %11110000 ; idem: wordt na 16* deze loop - met 16 verhoogd - LD (DY),A ; en vormt zo precies de - destination yco - - In deze routine wordt aan de hand van het nummer van het - blokje waarmee we bezig zijn berekent waar op het beeldscherm - dit blokje terecht moet komen. Kijk goed naar deze routine: - het is een vaak toegepast principe! Dit is alleen mogelijk - voor 16x16 blokjes (voor 8x8 valt wel iets soortgelijks te - bedenken) en dit is dan ook een van de redenen dat je als - programmeur de tekenaar altijd moet leren "in machten van 2" - te tekenen. - - SX,DX,DY en alle overige gegevens zijn nu ingevuld, dus het - blokje kan gekopieerd worden en de routine net zolang - herhaald tot het hele scherm vol is (merk op dit duurt een - fractie van een seconde voor 16*13=208 COPY's ). - - Maar dit was het helaas alweer voor deze keer. WE GAAN OP - FD #22 vrolijk verder met deze cursus... - - Ruud Gelissen diff --git a/Future Disk/21/Moonblaster Music Cursus 4.md b/Future Disk/21/Moonblaster Music Cursus 4.md deleted file mode 100644 index a802ef6..0000000 --- a/Future Disk/21/Moonblaster Music Cursus 4.md +++ /dev/null @@ -1,101 +0,0 @@ -Jorrith probeert de mensen weer aan te zetten tot het maken van riedels... - - - MOONBLASTER CURSUS part IV - - Hartelijk welkom beste lezer, bij alweer de vierde - aflevering van de MB-cursus. Een korte dit keer, het is - tenslotte voor mij ook vakantie !! (Voor de enige lezer - (Koen), voor het controleren van taalfouten zal het toch - niet veel meer uitmaken of ik nu veel of weinig onzin te - vertellen heb). Ik heb vorige keer een aantal dingen - beloofd. Zo beloofde ik bijvoorbeeld om met deze cursus een - of meerdere muziekstukken op te bouwen. Helaas komt dat er - door tijdgebrek nooit van, dus moet je gewoon de muziekjes - (die je in ieder geval t/m #20 nog in MoonBlaster in kan - lezen) maar eens helemaal met behulp van MB uitpluizen (heb - je wat te doen als je je verveeld!). Ik weet het, belofte - maakt schuld, maar ik heb me al aan zoveel dingen schuldig - gemaakt dat dit beetje er nog wel bij kan! - - BASSss - - In deze aflevering wilde ik het basgedeelte van een - muziekstuk bespreken. Voor je begint is het wel zo - verstandig om een bas-instrument te selecteren (Electric - bass 1 of 3 zijn 2 van mijn favorieten). Ik zal de rest aan - de hand van wat losse tips duidelijk proberen te maken. Voor - de zoveelste keer: als je het niet snapt kun je altijd - contact opnemen met de redactie. Ik heb nog nooit iemand - iemand gehad die het niet snapte. Op zich erg vreemd, ik kan - me niet voorstellen dat ik alles zo goed uitleg. Sterker - nog, ik weet zelfs niet altijd wat ik bedoel met hetgeen ik - getypt heb... - - Om een lang verhaal kort te maken komen hier enkele tips: - - - Gebruik een (of meerdere) lage octaven. Mijn persoonlijke - favorieten zijn octaaf 2 en 3(NvdR: die van mij 1 & 8). - - Om een bas te maken die niet vals klinkt kun je het beste - een beetje de hoogte van de laagste noot van een accoord - aanhouden. Dit is een nogal ingewikkelde zin, dus ik zal - hem even uitleggen aan de hand van een voorbeeldje. - Stel: Je hebt het volgende ingevoerd in MB: - - Step: 01 02 03 04 05 06 07 08 - Ch.1: A 4 OFF A 4 OFF A 4 OFF A 4 OFF - Ch.2: C 5 OFF C 5 OFF C 5 OFF C 5 OFF - Ch.3: E 5 OFF E 5 OFF F 5 OFF E 5 OFF - - Om nu een goed klinkende bas te maken moet je een beetje de - laagste noot van het accoord aanhouden, in dit geval dus de - "A". Het zou er dan zo uit kunnen zien: - - Step: 01 02 03 04 05 06 07 08 - Ch.1: A 4 OFF A 4 OFF A 4 OFF A 4 OFF - Ch.2: C 5 OFF C 5 OFF C 5 OFF C 5 OFF - Ch.3: E 5 OFF E 5 OFF F 5 OFF E 5 OFF - Ch.4: A 2 OFF A 2 OFF A 3 OFF A 2 OFF - - - Bij een rustig nummer hoort een rustige bas. Laat daarom - relatief veel ruimte vrij tussen de verschillende noten. - - Bij een snel nummer precies het tegenovergestelde: veel - noten, maar ook weer niet teveel. Als je het hele - baskanaal vol zet ben je een beetje te enthousiast - geweest... - - Doe af en toe wat afwisseling in de bas, dit zorgt vaak - voor schitterende resultaten. - - Een bas die steeds hetzelfde blijft, terwijl de accoorden - veranderen kan mooie resultaten hebben. - - Het springen van een lager octaaf naar 1 octaaf hoger - klinkt vaak erg goed. Spring daarna wel weer terug, zodat - je dit spelletje -indien gewenst- nog eens kan herhalen. - - Dit was zo'n beetje alles. Valt mee he? Als je eenmaal de - accoorden onder de knie hebt is de rest echt niet meer zo - moeilijk. - - OEFENING BAART KUNST - - Een oud spreekwoord, maar het blijft gelden. Hoe meer je het - doet hoe beter je erin wordt. Overigens geldt ditzelfde ook - voor OPL4, alleen moet je dan de genoemde octaven verlagen, - omdat dit nu eenmaal iets anders werkt. Goede kandidaten bij - OPL4 zijn voor een rustig nummer Slap bass (1 of 2) en - Fingered bass, bij het wat ruigere werk is Picked bass of - Synth bass (1 of 2) aan te bevelen. - - A little present - - Op deze disk staan (onder voorbehoud) de drumvoorbeelden van - de vorige keer. Ze stonden er wel op, maar niet zoals het - hoorde... Ook staan er nog twee voorbeelden op met daarin de - tot nu toe besproken onderwerpen, nl. de bas, de accoorden - en de drums. Zo houdt ik me toch nog een beetje aan m'n - belofte!(NvdR: misschien komt dit allemaal wegens - diskruimte gebrek te vervallen; schrik niet als de zooi niet - op de disk staat) - - Een prettige vakantie allemaal ! - - Jorrith "Vakantiestress..." Schaap diff --git a/Future Disk/21/Screen 12.md b/Future Disk/21/Screen 12.md deleted file mode 100644 index 4d146f8..0000000 --- a/Future Disk/21/Screen 12.md +++ /dev/null @@ -1,75 +0,0 @@ - Dhr. Keizer verheldert onze visie over screen 12 - - WHAT THE XXXX IS SCREEN12? - - ���� - ���� - ���� - ���� - - - Ik was een tijdje geleden bezig met de 2+ VDP. Omdat lang niet - alle omgebouwde 2-plussen ook 2 plusROMs hebben, mag dit dus - allemaal niet via de BIOS. De VDP direct aansturen dus. - Nu had ik eigenlijk geen flauw idee hoe dit allemaal moest - omdat ik geen data heb over de V9958. Dus, de telefoon maar - even gepakt, want dan ben je daar immer zo achter..... Niet - dus!!! Het aansturen van de V9958 schijnt echt een probleem - te zijn want zelfs de grote computer wizzzzkidzzz van MSX-end - Nederland konden me nog niet eens vertellen hoe ik screen 12 - aan moest zetten. Logisch was geweest om 12 in A (LD A,12) - en dan een call naar CHGMOD... NO ABSOLUTELY NOT! Waarom - weet ik niet maar dat was geloof ik een idee want er gebeurt - gewoon niets, maar wat dan wel?(NvdR: mijnheer Keizer, U - bent niet helemaal duidelijk meer) - Als eerst moet je blijkbaar screen 8 aanzetten, om daarna - "08" te zetten in register 25. Dus: - - SCRN12: LD A,08 - CALL CHGMOD - DI - LD A,08 - OUT ($99),A - LD A,128+15 - OUT ($99),A - EI - JP ?????? - - Dit kleine stukje source is genoeg om screen 12 aan te zetten - zonder dat er speciale 2+ BIOS routines worden gebruikt... - Om te kijken of er wel een V9958 aanwezig is, is het volgende - stukje source nodig: - - V9958?: DI - LD A,$01 - OUT ($99),A - LD A,$8F - OUT ($99),A - PUSH AF - POP AF - IN A,($99) - LD D,A - XOR A - OUT ($99),A - LD A,$8F - OUT ($99),A - EI - VDP-JP: LD A,D - AND $3E - JP NZ,V9938R - JP V9958R - - Dit stukje source kijkt dus ook echt alleen of er een V9958 is - zonder naar ROMS te kijken, iets dat veel programma's nog eens - willen doen. Een normale MSX2 met daarin dus een V9958 wordt - dus tot 2+ gebombardeerd door deze routine. Dat was 't wel, - verder moet je screen 12 als screen 8 behandelen en om overig- - ens screen 11 te krijgen moet je de "08" die je naar register - 25 out vervangen door "24", decimaal dus... - - Van wie ik deze wijsheid heb?? Lijkt me vrij duidelijk... - Van de MSX programmeur in Nederland, Alex Wulms. - - Well, good luck... I guess?!?! - -Tobias "Thank you Alex" Keizer diff --git a/Future Disk/22/Data compressie 5.md b/Future Disk/22/Data compressie 5.md deleted file mode 100644 index bf42670..0000000 --- a/Future Disk/22/Data compressie 5.md +++ /dev/null @@ -1,1055 +0,0 @@ - Jan-Willem bazelt weer over dingen die een simpele ziel als ik nooit zal begrijpen... - - Data Compressie 5 (?) - - Jaa, sorry hoor, maar ik ben de tel kwijt geraakt. Niet dat - er zoveel cursi waren, maar ik heb al een keer of 4 niks - meer gedaan, of beloofd dat ik de listing zou gaan - bespreken. Belofte maakt schuld, dus .... - - RUNLEN.GEN - - AL MIJN COMMENTAAR KOMT NU IN GROTE LETTERS. ZO ZIE JE HET - VERSCHIL TUSSEN COMMENTAAR EN LISTING MAKKELIJKER. - - WE STARTEN MET WAT COMMANDO'S VOOR DE ASSEMBLER (IN DIT - GEVAL GEN80). - -* g 0,s 15 - - HIERNA VOLGEN ENIGE COMMENTAAR REGELTJES.... - -; Runlength v3.0 1995 -; (c) Jan-Willem van Helden -; Thanks to: -; - Ivo Wubbels & Falco Dam -; - David Huffman -; - Lempel-Ziv Welch - -; de JCP file ziet er zo uit: - -; - codebyte1 (1) -; - codebyte2 (1) -; - x-offset (1) -; - y-offset (1) -; - paletbit (1) (als 0 geen palette) -; als palette=0: volgende 32 bytes palette -; daarna komt data - - IK BEGIN MET EEN KLEINE SETUP, DIE NODIG IS VOOR MSX-DOS. - HET IS ALTIJD HANDIG OM EEN MACRO TE EDITTEN VOOR DE BIOS - CALLS. - -bios: macro @bios1 - ld iy,(#fcc0) - ld ix,@bios1 - call #1c - endm - - EEN MACRO OM TEKSTEN AF TE DRUKKEN - -printaf: macro @printaf1 - ld de,@printaf1 - ld c,#9 - call #f37d - ld de,nexttext - ld c,#9 - call #f37d - endm - - OM DE RST20 TE SIMULEREN - -rst20: macro - ld a,h - sub d - jr nz,$+4 - ld a,l - sub e - endm - - NOG EEN MACRO DIE WE LATER NODIG HEBBEN - -searchtabel: macro - ld ix,tabel - ld iy,tabel+2 - ld b,-1 -;tabelsrc: - ld l,(ix+0) ;in HL de laagste - ld h,(ix+1) - ld e,(iy+0) ;in DE de hogere - ld d,(iy+1) - - rst20 - - jp c,$+7 ;DE hoger ?? -> nieuwe laagste - - push iy - pop ix -;--- - inc iy - inc iy - djnz $-26 - - push ix - pop hl - ld de,tabel - and a - sbc hl,de - and a - rr h - rr l - ld a,l - endm - - EEN LAATSTE AANTAL EQU'S - -bdos: equ #f37d -datfil: equ #8000 -regelv: equ 128 -tabel: equ #d000 - - ld a,(#f342) ; zet RAM op #4000 - ld h,#40 - call #24 - - ld hl,#5c ; zet de 2e filenaam in - ld de,fcb ; het File Control Block - ld bc,12 - ldir - - ld hl,#82 ; bekijk de rest van de - ld de,verwerking ; commandline - ld bc,#100-#82 - ldir - - ld hl,tabel ; vul de tabel met nullen - ld de,tabel+1 - ld bc,(256*2)-1 - ld (hl),0 - ldir - - ld e,"/" ; zoek naar de file options - ld hl,verwerking - call cmpr - call z,fndslash - - printaf starttext - - - ld de,free ; DMA op einde van de file - ld c,#1a ; zetten - call bdos - - ld de,fcb ; file openen - ld c,#0f - call bdos - or a - jp nz,endsequence ; error - - ld hl,0 - ld (blok),hl - ld (blok+2),hl - ld (#f3ea),hl - inc hl - ld (grote),hl - - ld a,(depacking) ; kijken of we soms moeten - and a ; uitpakken i.p.v. inpakken - jp nz,depacker - - printaf starttext1 ; nee hoor, we gaan inpakken - - ld hl,(filsiz) - call fulprt - - printaf decstr - - printaf savetext - - ld c,#1 ; kijken of we 'm moeten - call bdos ; inpakken of der mee - cp "s" ; moeten stoppen - jp z,loadpicture - cp "S" - jp nz,closefile - -; nu wordt het plaatje daadwerkelijk ingeladen - -loadpicture: - ld hl,(filsiz) - ld (fil_siz),hl - ld a,(screen) ; gekozen scherm aanzetten - bios #5f - ld a,(screen12) - inc a - jp nz,n_setscreen12 - ld bc,#819 ; screen 12 aan - bios #47 -n_setscreen12: - ld a,(#ffe7) ; sprites uit - or 2 - ld b,a - ld c,8 - bios #47 - ld de,#8000 ; dma op #8000 - ld c,#1a - call bdos - ld hl,4 ; eerste 4 bytes inladen - ld de,fcb - ld c,#27 - call bdos - -;kijken of het een .DAT/.GE5 file is - - ld a,(#8000) - cp #fe - jp nz,loadpicture_d ;dat file - ld hl,3 - ld de,fcb - ld c,#27 - call bdos - jp loadpicture_b ;bin file - - EEN DAT-FILE BEGINT ALTIJD MET DE X-LENGTE (2-BYTES) EN DE - Y-LENGTE. DEZE ZIJN GEGEVEN IN DOTS. OM ZE OM TE REKENEN - NAAR REEELE BYTES, ZIE HET VOLGENDE -(IN DE VOLGENDE TEXT!). - Jan-Willem bazelt weer over dingen die een simpele ziel als ik nooit zal begrijpen... - - Data Compressie 5 (?) - -(VERVOLG) - -loadpicture_d: - ld hl,(#8000) -; in geval van screen 5: delen door 2 -; 6: 4 -; 7: 2 -; 8: 1 - - ld a,(screen) - cp 8 - jp nc,loaddatloop2_1 - and a - rr h - rr l - cp 6 - jr nz,loaddatloop2_1 - and a - rr h - rr l -loaddatloop2_1: - ld a,l - dec a - ld (xofset),a ; mijn x-offset vullen - ld a,(#8002) ; y-offset bepalen - ld c,a - dec a - ld (yofset),a - ld hl,(vrmpnt) ; gelijk aan 0 - call loaddatfl ; blokje inladen -loaddatloop: - push bc - ld bc,(xofset) - inc c -loaddatloop2: - ld a,(de) ;werkelijke naar het - call putintable ;scherm toeschrijven - bios #177 - inc hl - inc de - push hl - ld hl,#c000 - rst20 - call z,loaddatfl - pop hl - dec c - jp nz,loaddatloop2 - ld hl,(vrmpnt) ; naar het begin van de - push de ; volgende regel - ld de,256 - ld a,(screen) ; opletten met die screens ! - cp 7 - jp nc,loaddatloop3 - ld de,128 -loaddatloop3: - add hl,de - ld (vrmpnt),hl - pop de - pop bc - dec c - jp nz,loaddatloop ; blijven doen totdat datfile - ; op het scherm staat - ld a,(nopaletdat) - inc a - jp z,loadpicture1 ; palet switch disabeled - ex de,hl - ld b,32 ; anders nog even het palet - ld de,palet ; inladen (kan alleen bij -paletdatl: ; dat files gemaakt door - ld a,(hl) ; DD-Graph. - ld (de),a - push de - inc hl - ld de,#c000 - rst20 - pop de - inc de - call z,loaddatfl - djnz paletdatl - - ld hl,palet ; paletje aanzetten. - call setpal - - jp loadpicture1 -loaddatfl: ; het daadwerkelijke laden - push bc ; van de dat-file - push hl - ld de,#8000 - ld c,#1a - call bdos - ld hl,#4000 - ld de,fcb - ld c,#27 - call bdos - ld de,#8000 - pop hl - pop bc - ret -; binaire files inladen - - BINAIRE FILES ZIJN EEN STUK MAKKELIJKER. JE HOEFT ALLEEN - MAAR TE LADEN TOT HET EINDADRES EN DAT NAAR HET VIDEORAM TE - DUMPEN. - -loadpicture_b: -;voor screen 5 geldt: 127 -; 6 127 -; 7 255 -; 8 255 voor de X-offset - ld a,(screen) - cp 7 - ld a,255 - jp nc,loadbinary - ld a,127 -loadbinary: - ld (xofset),a - ld hl,(screenlength) - ld (screen_length),hl - ld de,-#4000 -loadpicturel: - ex de,hl - ld de,#4000 - add hl,de - ex de,hl - push de - ld de,#8000 - ld c,#1a - call bdos - ld hl,#4000 - ld de,fcb - ld c,#27 - call bdos - ld hl,#8000 - ld bc,#4000 - pop de - push de - ex de,hl -loadpicture2: - ld a,(screen) - cp 7 - push de - ld d,h - ld a,211 - jr nc,loaddicture - and a - rl d ; keer 2 !!! -loaddicture: - cp d - pop de - ld a,(de) - call c,putintable - bios #177 - inc hl - inc de - dec bc - ld a,b - or c - jp nz,loadpicture2 - - ld hl,(fil_siz) - ld de,#4000 - and a - sbc hl,de - ld (fil_siz),hl - pop de - jp nc,loadpicturel - ld a,211 - ld (yofset),a - ld hl,(paletdata) ; palet nog binnenhalen - ld a,h - or l - jp z,loadpicture1 - ld de,palet - ld bc,32 - bios #59 - ld hl,palet - call setpal -loadpicture1: - call close_file_real - - BIJ HET INLADEN NET WERD PER BYTE DE ROUTINE PUTINTABLE - AANGEROEPEN. DEZE ROUTINE MAAKT EEN TABEL AAN MET DE - WAARDEN VAN HET AANTAL KEER VOORKOMEN VAN DE BYTE. ENKELE - CURSI TERUG HEB IK UITGELEGD, DAT JE OM EEN GOEDE COMPRESSIE - TE KRIJGEN DE MINST VOORKOMENDE BYTE ALS CODE-BYTE MOET - GEBRUIKEN. IN DE VOLGENDE ROUTINE DOEN WE DAT. ALS - UITBREIDING ZOEKEN WE OOK NOG EEN 2E CODE-BYTE. NU KUNNEN WE - ZOWEL IN 1 ALS IN 2 BYTE(S) CRUNCHEN - - -; nu wordt de minst voorkomende waarde gezocht - - searchtabel - ld (codebyte1),a - ld (ix+0),#ff ; die positie effe vullen - ld (ix+1),#ff ; (meest voorkomend maken) - -; nu wordt de een na minst voorkomende waarde gezocht - - searchtabel - ld (codebyte2),a - -; de codebyte is gevonden -; nu wordt alles klaargemaakt om het crunchen te beginnen - - ld hl,jwext ;die coole .JCP - ld de,ext - ld bc,3 - ldir - - xor a - ld (fcb),a ; defaultdrive - - ld de,fcb ; file aanmaken - ld c,#16 - call bdos - - ld hl,0 - ld (blok),hl - ld (blok+2),hl - inc hl - ld (grote),hl - -; create header - - ld a,(codebyte1) - ld (dma),a - ld a,(codebyte2) - ld (dma+1),a - ld a,(xofset) - ld (dma+2),a - ld a,(yofset) - ld (dma+3),a - - ld de,dma ; header wegschrijven - ld hl,4 - call crnstoreit - - ld a,(nopaletdat) ; palet storen ? - ld (dma1),a - ld de,dma1 - ld hl,1 - push af - call crnstoreit - pop af - inc a - jp z,nostorepal ; zo ja, dan zijn de - ; volgende 32 bytes paletdata - ld de,palet - ld hl,32 - call crnstoreit - - NU GEBRUIK IK WEER DIE SEMI PROGRAMMEER TAAL DIE OOK IN DE - VORIGE CURSI GEBRUIKT WERD. - -nostorepal: - ld hl,0 ; A - ld (vrmpnt),hl -crnrestart: - ld bc,1 ; CNTR=0 - bios #174 ; get A - ld d,a - xor #ff - bios #177 -crnloop: - call crnendline ; A+1 wordt geset in crnendline - ld a,(endfile) - and a - jp nz,crnstore - bios #174 ; get A+1 - cp d ; A=A+1 ? - jp nz,crnstore ; NO - xor #ff - bios #177 ; laat vooruitgang zien - inc bc - jp crnloop ; YEP -crnstore: - push hl - push de - ld h,b - ld l,c - ld d,0 - ld e,3+1 ; is CNTR > 3 ??? (nieuw idee) - rst20 - pop de - pop hl - jp nc,crnstore1 ; ja - ld a,(codebyte1) ; check of het 1 van de 2 - cp d ; codebytes is - jp z,crnstore1 ; ja, dan store ze als crunch - ld a,(codebyte2) ; data - cp d - jp z,crnstore1 - push hl ; zijn ze dat niet, schrijf - push bc ; dan het aantal keer de byte - ld b,c ; naar de disk - ld hl,dma1 -crnstore2: - ld (hl),d - inc hl - djnz crnstore2 - pop hl - ld de,dma1 - call crnstoreit - pop hl - ld a,(endfile) ; einde ? - dec a - jp z,closefile - jp crnrestart ; begin aan de volgende byte -crnstore1: - ld a,d - ld (dma+1),a ; STORE A - ld a,b ; A kleiner dan 256 ? - and a ; store dan maar 3 bytes - jp z,crnstore3bytes - ld a,(codebyte1) ; store codebyte - ld (dma),a - ld (dma+2),bc ; STORE CNTR - push hl - ld hl,4 -crnstore3: - ld de,dma - call crnstoreit ; STORE de hele heise - pop hl - ld a,(endfile) ; einde ? - dec a - jp z,closefile - jp crnrestart ; begin aan volgende byte -crnstore3bytes: - ld a,(codebyte2) ; schrijf maar 3 bytes weg - ld (dma),a - ld a,c - ld (dma+2),a - push hl - ld hl,3 - jp crnstore3 -crnstoreit: - push hl ; het wegschrijven - ld c,#1a - call bdos - pop hl - ld de,fcb - ld c,#26 - jp bdos -crnendline: - push bc ; routine om te bepalen of - push de ; we het einde van de regel - ld d,l ; bereikt hebben - ld a,(screen) - cp 7 - jp nc,nietdelen - ld a,d - sub 128 - jp c,nietdelen - ld d,a -nietdelen: - ld a,(xofset) - cp d - jp nz,crnendline3 - ld a,(screen) - ld hl,(vrmpnt) - ld de,256 - cp 7 - jr nc,crnendline2 - ld de,128 -crnendline2: - add hl,de - ld (vrmpnt),hl - cp 7 - ld d,h - ld a,(yofset) - jr nc,crnendline4 - and a - rl d ; keer 2 !!! -crnendline4: - cp d - jr nc,crnendline3_1 - pop de - pop bc - ld a,1 - ld (endfile),a - ret -crnendline3: - inc hl -crnendline3_1: - pop de - pop bc - ret -closefile: - xor a ; einde van het programma - bios #5f ; scherm 0 aan - ld hl,stndpalet ; standaard palet aan - call setpal -close_file: - call close_file_real ; file sluiten - ld c,0 - jp bdos ; exit met system-reset -close_file_real: - ld de,fcb - ld c,#10 - jp bdos - - IN DIT PROGRAMMA ZIT OOK GELIJK DE UITPAKKER. - - (LEES DIE IN TEKST(3))! - - Jan-Willem bazelt weer over dingen die een simpele ziel als ik nooit zal begrijpen... - - Data Compressie 5 (?) - -(VERVOLG VERVOLG) - -depacker: - printaf depacktext - - ld c,#1 ; kijken of we moeten uit- - call bdos ; pakken of stoppen - cp "d" - jp z,loaddepackdat - cp "D" - jp nz,closefile -loaddepackdat: - ld de,free ; dma op vrije plaats - ld c,#1a - call bdos - - ld hl,(filsiz) ; file laden - ld de,fcb - ld c,#27 - call bdos - - ld a,(screen) ; schermpje aan - bios #5f - - ld a,(free) ; data vullen - ld (codebyte1),a - ld a,(free+1) - ld (codebyte2),a - ld a,(free+2) - ld (xofset),a - ld a,(free+3) - ld (yofset),a - ld a,(free+4) - and a - ld de,free+5 - jp nz,nodepackpalet; palet checken - ld hl,free+5 - ld de,palet - ld bc,32 - ldir - ld hl,palet - call setpal - ld de,free+5+32 -nodepackpalet: ; de werkelijke depacker - ld hl,0 ; startadres in VRAM -depackrout: - ld a,(de) ; GET data - ld b,a - ld a,(codebyte2) ; data = CODEBYTE2 ? - cp b - jp z,depack1loop - ld a,(codebyte1) ; data = CODEBYTE1 ? - cp b - jp z,depackloop - ld a,(de) ; NO - bios #177 ; WRITE data TO VRAM - inc de - call crnendline ; endline ? - ld a,(endfile) ; einde ? - and a - jp nz,enddepack - jp depackrout ; volgende data -depackloop: - inc de ; GET A - ld a,(de) - ex af,af' - inc de - ld a,(de) ; GET CNTR - ld c,a - inc de - ld a,(de) - ld b,a -depack_loop: - ex af,af' - bios #177 ; DUMP A CNTR times - ex af,af' - call crnendline ; endline ? - ld a,(endfile) ; einde ? - and a - jp nz,enddepack - dec bc - ld a,b - or c - jp nz,depack_loop - ex af,af' - inc de - jp depackrout ; next data -depack1loop: - inc de - ld a,(de) ; GET A - ex af,af' - inc de - ld a,(de) ; GET CNTR (1 byte) - ld c,a - ld b,0 - jp depack_loop -enddepack: - ld c,#1 ; input ? - call bdos - jp closefile ; einde programma - - HET EIGENLIJKE PROGRAMMA IS NU GEDAAN. ALLEEN NOG ENKELE - SUB-ROUTINES VOLGEN - -putintable: ; tabel vullen - push de - push bc - ld b,a - inc b - ld ix,tabel-2 - ld de,2 -putintablel: - add ix,de - djnz putintablel - - ld c,(ix+0) - ld b,(ix+1) - inc bc - ld (ix+0),c - ld (ix+1),b - pop bc - pop de - ret -fndslash: ; zoeken naar de / - inc hl - ld a,"5" ; scherm bepalen - cp (hl) - jp z,scr5 - ld a,"6" - cp (hl) - jp z,scr6 - ld a,"7" - cp (hl) - jp z,scr7 - ld a,"8" - cp (hl) - jp z,scr8 - ld a,"1" - cp (hl) - jp z,scr12 -nextpart: - inc hl ; zoeken naar de P - ld a,"," - cp (hl) - ret nz - inc hl - ld a,"P" - cp (hl) - call z,nopaleton ; palet aan cq uit - ld a,"p" - cp (hl) - call z,nopaleton - inc hl - ld a,"," - cp (hl) - ret nz - inc hl - ld a,"D" ; depacker ? - cp (hl) - call z,depackon - ld a,"d" - cp (hl) - call z,depackon - ret - -; waarden goed vullen - -nopaleton: - ld a,-1 - ld (nopaletdat),a - ld de,0 - ld (paletdata),de - ret -depackon: - ld a,-1 - ld (depacking),a - ret -scr5: - ex de,hl - ld a,5 - ld (screen),a - ld hl,#7680 - ld (paletdata),hl - ld hl,128*212 - ld (screenlength),hl - ld a,128-1 - ld (xofset),a - ex de,hl - jp nextpart -scr6: - ex de,hl - ld a,6 - ld (screen),a - ld hl,#7680 - ld (paletdata),hl - ld hl,128*212 - ld (screenlength),hl - ld a,128-1 - ld (xofset),a - ex de,hl - jp nextpart -scr7: - ex de,hl - ld a,7 - ld (screen),a - ld hl,#fa80 - ld (paletdata),hl - ld hl,256*212 - ld (screenlength),hl - ld a,-1 - ld (xofset),a - ex de,hl - jp nextpart -scr8: - ex de,hl - ld a,8 - ld (screen),a - ld hl,0 - ld (paletdata),hl - ld hl,256*212 - ld (screenlength),hl - ld a,-1 - ld (nopaletdat),a - ld (xofset),a - ex de,hl - jp nextpart -scr12: - inc hl - ld a,"2" - cp (hl) - ret nz - ld a,-1 - ld (screen12),a - jp scr8 - -; ontzettend moeilijke en tegelijk zeer interessante routine ! - -beep: - bios #c0 - ret - -cmpr: - ld a,e - cp (hl) - ret z - inc hl - ld a,(hl) - and a - jp nz,cmpr - inc a - ret -endsequence: ; routine als er geen input - printaf endtxt ; is - ret - -; de texten - -endtxt: - db "Opts are: " - db "/n: MSX2/2+ screen number; /P: No palette" - db 10,13 - db "/D: depack file",10,10,13 - db "Default: A>RUNLEN filename /n,P,D$" -depacktext: - db "Press [D] to depack or any other key to quit" - db "$" -starttext: - db "Runlength V3.0",10,13,"$" -starttext1: - db 10,"File length: $" -savetext: - db 10,"Press [S] to save or any other key to quit" - db "$" -runlentxt: - db "RUNLEN" -nexttext: - db 10,13,"$" - -; variabelen - -verwerking: ds #100-#82 -screenlength: dw 0 -screen_length: dw 0 -depacking: db 0 -screen: db 8 -fil_siz: dw 0 -paletdata: dw 0 -palet: ds 32 -nopaletdat: db 0 -xofset: db 0 -yofset: db 0 -vrmpnt: dw 0 -stndpalet: dw 0,0,#611,#733,#117,#327,#151,#627 - dw #171,#373,#661 - dw #663,#411,#265,#555,#777 -screen12: db 0 -endfile: db 0 -codebyte1: db 0 -codebyte2: db 0 -dma: - -; Stukjes om weg te schrijven - - db 0 ; Codering - db 0 ; Gelezen waarde - dw 0 ; Countr waarde -dma1: ds 4 -jwext: db "JCP" -setpal: - push hl - ld bc,16 - bios #47 - pop hl - ld bc,#209a - otir - ret -ascbin: push de - push hl - ld hl,0 - ld (ascnum),hl - ld (ascnum+2),hl - pop hl -asclus: - ld a,(hl) - sub "0" - jp m,asceind - cp 10 - jp p,asceind - push hl - call maal10 - pop hl - inc hl - jp asclus -asceind: - pop de - push hl - ld hl,ascnum - ld bc,4 - ldir - pop hl - ret -maal10: - ld iy,(ascnum) - ld hl,(ascnum+2) - add iy,iy - adc hl,hl - ld e,l - ld d,h - push iy - pop bc - add iy,iy - adc hl,hl - add iy,iy - adc hl,hl - add iy,bc - adc hl,de - ld c,a - ld b,0 - add iy,bc - ld c,0 - adc hl,bc - ld (ascnum),iy - ld (ascnum+2),hl - ret - -ascnum: ds 4 - -fulprt: - ld de,decstr - ld b,7 - ld a,"$" -dc1: ld (de),a - inc de - djnz dc1 -dc2: xor a - ld e,a - ld b,16 -dc3: rl l - rl h - rl e - ld a,e - sub 10 - ccf - jr nc,dc4 - ld e,a -dc4: djnz dc3 - rl l - rl h - ld a,e - add a,"0" - push hl - ld hl,decstr+3 - ld de,decstr+4 - ld bc,4 - lddr - ld (decstr),a - pop hl - ld a,h - or l - jr nz,dc2 - ret -decstr: ds 7 - -fcb: db 0 -name: -inputfile: db "12345678" -ext: db "123" - dw 0 -grote: dw 0 -filsiz: ds 17 -blok: dw 0,0 -free: -einde: - end - - Zo, nu is dat hoofdstuk helemaal afgesloten. Volgende keer - gaan we eens aan de slag met Huffman. Niet zo moeilijk, - goede resultaten, maar erg traag voor de MSX. - - De bovenstaande listing staat op disk onder de naam - "RUNLEN.GEN" en is public domain. - - Zo, vaerdig ! - - Jan-Willem van Helden diff --git a/Future Disk/22/Moonblaster Music Cursus 5.md b/Future Disk/22/Moonblaster Music Cursus 5.md deleted file mode 100644 index 3a28f6e..0000000 --- a/Future Disk/22/Moonblaster Music Cursus 5.md +++ /dev/null @@ -1,324 +0,0 @@ - Hehe die fuck cursus is bijna afgelopen... - - - MOONBLASTER CURSUS - - The semi-final part - - - Degenen die deze cursus al van begin af aan volgen - herinneren zich misschien nog de uitleg van een zekere - Stefan Boer(NvdR: Wie?). Hij zou mij nog een tekst sturen - over de accoorden. Half Augustus werd deze belofte eindelijk - een feit, zodat jullie alsnog de beloofde informatie krijgen. - - Nog een stukje citaat uit de begeleidende brief: "Met behulp - van een beetje muziektheorie wordt zelf muziek maken veel - makkelijker, omdat je dan veel eerder ziet welk accoord of - welke bas ergens bij past en welke noten ergens bij kunnen - zonder dat het vals wordt." Zo, nou hoor je het ook eens van - iemand anders, stelletje wijsneuzen! - - De rest van deze tekst is gewoon letterlijk overgetypt - (waarom hij de tekstfile niet heeft meegestuurd is me ook - een raadsel), dus voor commentaar ben je bij mij aan het - verkeerde adres. Het woord is aan Stefan. - - ACCOORDEN - - Accoorden zijn drie- of vierklanken. In de paragraaf over - begeleiding zal ik uitleggen hoe u accoorden in uw - muziekstukken kunt gebruiken. Maar nu eerst de opbouw van - een accoord. - - De grondtoon is de toon waaraan het accoord zijn naam - ontleent. Voor het C-accoord is dat dus de C. Het "normale" - of majeur accoord bestaat verder uit de 3e(NvdR: terts) en - 5e (kwint) toon uit de majeur toonladder van de grondtoon. - Dat klinkt heel ingewikkeld, maar het valt best mee. De - C-toonladder kent iedereen: - - C D E F G A B C - do re mi fa sol la ti do - - Het C-accoord is dus opgebouwd uit de grondtoon C, de derde - toon E en de kwint (vijfde toon) G: C-E-G. - - Alle toonladders: [niet echt "alle] - ------------------------------------------------------------- - C D E F G A B C C-toonladder - C# D# F F# G# A# C C# Cis/Des-toonladder - D E F# G A B C# D D-toonladder - D# F G G# A# C D# E Dis/Es-toonladder - E F# G# A B C# E F E-toonladder - F G A A# C D F F# F-toonladder - F# G# A# B C# D# F# G Fis/Ges-toonladder - G A B C D E G G# G-toonladder - G# A# C C# D# F G# A Gis/As-toonladder - A B C# D E F# A A# A-toonladder - A# C D D# F G A# B Ais/Bes-toonladder - B C# D# E F# G# B C B-toonladder - ------------------------------------------------------------- - - N.B. ik heb hier dezelfde notatie gebruikt als in - MoonBlaster, omdat er geen mol in de karakterset zit. Een A# - is dus hetzelfde als een Bes. Als u in MoonBlaster dus een - As nodig hebt, gebruik dan een Gis. - - Voorbeelden: - - 1) Dis accoord - 2) Bes accoord - 3) F accoord - 4) B accoord - 5) E accoord - - 1) Dis-G-Ais - 2) Bes-D-F - 3) F-A-C - 4) B-Dis-Fis - 5) E-Gis-B - - VARIATIES VAN ACCOORDEN - - Behalve het gewone accoord kom je ook veel accoorden met - toevoegingen tegen. Bijvoorbeeld C6, Fm, G7, Dm6, Am7, C+, - Fmaj7(NvdR: Dsus4, Dsus2). - - Een overzicht: - - C6 Dit is het C-accoord, echter met nog een "zesde" toon - eraan toegevoegd. Die zesde toon ligt drie halve - toonafstanden onder de grondtoon. Voor de C is dat - dus de A. Het C6 accoord wordt dus: CEGA - Fm Dit is een F-mineur accoord. De derde toon wordt met - een halve toon verlaagd. De A wordt dus As: F-As-C. - G7 Dit is een G-septiem accoord. Er komt nog een - "zevende" toon bij. De septiem-toon ligt twee halve - toonafstanden onder de grondtoon. Dat is voor het - G-accoord de F: G-B-D-F - Dm6 Dit is een combinatie van D6 en Dm. Het wordt dus: - D-F-A-B. - Am7 Dit is een combinatie van Am en A7. Het wordt dus: - A-C-E-G. - C+ Dit is een zogenaamde overmatige drieklank. De kwint - wordt met een halve verhoogd. Het C+ accoord luidt - dus: C-E-Gis. - Fmaj7 Aan het F-accoord wordt nog een toon toegevoegd, die - een halve toonafstand onder de grondtoon ligt. Het - F-accoord wordt dus F-A-C-E. - - Met een halve toonafstand wordt de afstand tussen twee - toetsen bedoeld. Dus de afstand tussen E en F of de afstand - tussen Fis en G. - - Voorbeelden: - - 1) C7 6) B7 - 2) Bes6 7) Esm7 - 3) Cmaj7 8) D7 - 4) Gm7 9) Fmaj7 - 5) Em 10) A6 - - 1) C-E-G-Bes 6) B-Dis-Fis-A - 2) Bes-D-F-G 7) Es-Ges-Bes-Des - 3) C-E-G-B 8) D-Fis-A-C - 4) G-Bes-D-F 9) F-A-C-E - 5) E-G-B 10) A-Cis-E-Fis - - - GRONDLIGGING - - De hierboven behandelde volgorde van tonen van een accoord - heet de grondligging. De accoorden hoeven niet perse in deze - volgorde te staan. U kunt ook de hoogste toon naar onder - halen of de laagste toon naar boven. Het F-accoord wordt - bijvoorbeeld vaak afgespeeld als A-C-F. - - - ACCOORD MET MINDER TONEN - - U kunt van een vierstemmig accoord een driestemmig maken - of van een driestemmig een tweestemmig door de kwint weg te - laten. - - U kunt van een vierstemmig accoord geen tweestemmig accoord - maken zonder dat u iets weglaat (dus Em7 wordt of E7 of Em). - U kunt dan zelf kiezen wat het beste klinkt. - - Dit kannodig zijn omdat u soms niet genoeg kanalen heeft. - Als u bij MoonBlaster bijvoorbeeld 3 kanalen voor de melodie - nodig heeft en 1 voor de bas, dan heeft u maar 2 kanalen - over voor de accoorden. - - M.D.A. - - (jawel jawel) - Stefan Boer - - - Nog een paar opmerkingen achteraf: ik heb hier maar een - paar wijzigingen in aangebracht (SoundTracker vervangen door - MoonBlaster, en een gedeelte m.b.t. bladmuziek - overschrijven. Deze tekst is voor de rest gewoon zoals ik - hem kreeg. Voor commentaar over deze tekst ben ik dus niet - bereikbaar :-) - (NvdR: en Stefan ook niet, want die zit op dit moment Japanse - meisjes te versieren. Okay, maybe not) - Eindelijk het laatste deel van die rotcursus van Jorrith! - - -MoonBlaster cursus - Final Part - - - Jaaahhh, geachte fans, alweer het laatste deel van de - MoonBlaster cursus. In deze cursus wilde ik als laatste - onderdeel de melodie behandelen, en geef ik als afsluiting - nog wat handige tips. Misschien nog wel meer, maar dat kan - ik nu nog niet zeggen (ik zit pas aan het begin van deze - tekst). Lees maar gewoon, dan merk je het vanzelf... - - De melodie - - De melodie is het belangrijkste onderdeel van een - muziekstuk. Zonder een melodie is een muziekstuk meestal - saai (hoeft niet natuurlijk, dat ligt aan jezelf). Zelf heb - ik me nog nooit echt intensief bezig gehouden met het maken - van een goede melodie. Daar heb je als redactielid of geen - tijd voor of geen zin in. - Maar om het kort te houden geef ik, net zoals in de vorige - afleveringen een soortement richtlijnen, en wie weet kun je - d'r wat mee... - - - Wijk niet teveel af van het accoord/ de accoorden die op - hetzelfde moment spelen. Hiermee bedoel ik dus: als je een - accoord hebt (bv. A 4 - C 5 - E 5), ga dan niet eigenwijs - zitten doen door een D of een B af te spelen, want meestal - klinkt dat gewoon niet. Als je het accoord zou veranderen - in bv. A 4 - B 4 - D 5, dan kan het natuurlijk weer wel, - maar dan zal een C of een E vaak niet mooi klinken. - Natuurlijk is het ook wel handig om in een muziekstuk vaak - van accoord te wisselen. - - Als je de achtergrond voor een muziekstuk eenmaal af hebt - (dus de drums, de bas en de accoorden) kun je dit gewoon - afspelen en ondertussen een melodie bedenken. Zelf doe ik - dit echter nooit, maar misschien heb je er wat aan. - - Als je eenmaal een mooie melodie in je kop hebt zitten - kun je, als het niet klinkt met de accoorden, twee dingen - doen. Of je verandert de melodie, of de achtergrond (de - bas en de accoorden). Bij mij komt het echter meestal op - het eerste neer... - - Een melodie waarin je weinig lege ruimtes hebt is vaak - niet mooi. Als je een heel druk muziekstuk wilt maken is - dit echter wel de beste methode, en als je de versterker - flink hard zet ben je ook gelijk van je buren af! - - Bij een rustig nummer moet je geen schelle instrumenten - gebruiken, bij een wat ruiger nummer echter juist wel. - - Als je eenmaal een achtergrondje hebt gemaakt kun je - hierin ook wijzigingen maken, zodat je een mooie overgang - van de ene melodie krijgt naar de andere. Laat bv. de - drums eens weg, of de bas (of vervang ze). - - Zo, dit was het wel zo'n beetje wat betrefd de melodie. - Natuurlijk blijft gelden: OEFENING BAART KUNST(en soms - kinderen). Als je je er echt serieus mee bezig wilt houden - moet je gewoon blijven klooien, het wordt vanzelf beter. - Noten kunnen lezen is niet nodig, en raak niet in paniek - als het niet lukt (anders krijgen wel allemaal half-maffe - leden die hun abonnement niet kunnen verlengen....). - - En toen kwam de rest... - - Tja, als opvulling kan ik alleen nog maar wat kleine tips - geven. Het is niet anders, maar aan alles komt nou eenmaal - een eind, dus ook aan deze cursus. Ik heb jullie nu alweer - genoeg verveeld, dus ga ik maar snel weer verder met 'the - technical stuff'. - -Tip 1: - - Als je een muziekstuk aan het maken bent, en je komt - patterns of noten tekort dan kun je het volgende doen. Bij - een pattern-tekort moet je het tempo zo verlagen dat de - snelheid precies 2x zo laag is. De 'formule' geef ik straks - wel, eerst het nut. Als je met een langzaam muziekstuk bezig - bent (en je hebt tussen de noten onderling nog (minstens) ��n - lege ruimte) dan kun je de helft van de patterns besparen - door alle noten naar boven te verhuizen. Er kunnen dan de - noten van 2 patterns op de ruimte van een pattern. Omdat dit - dan 2x langzamer afgespeeld wordt, duurt het muziekstuk dan - net zo lang, alleen heb je dan extra patterns over. Dit - werkt echter niet als de noten elkaar al direct opvolgen. - Bij OPL4 maakt dit niet zoveel uit, omdat je dan toch zoveel - kanalen hebt, zodat je de informatie uit een kanaal over 2 - kanalen kunt verdelen. - Het tegenovergestelde is ook mogelijk. Stel, je hebt te - weinig ruimte om alle noten te plaatsen die je wilt - plaatsen. Je wilt dus als het ware in het huidige tempo een - halve noot invoeren (bv. tussen step 7 en 8). Dit is te - verhelpen door het tempo 2x sneller te maken, zodat de data - van 1 pattern over 2 verspreidt kan worden. En nu werkt het - wel.... - Als afsluiting van deze tip nog even de formule: - - 25 - huidig tempo = een uitkomst (nee maar!) - - Als je het tempo 2x zo snel wilt hebben moet je deze waarde - delen door 2 (2x zo langzaam is vermenigvuldigen met 2). - Hieruit krijg je weer een bepaalde uitkomst, die je van 25 - af moet trekken om het gewenste resultaat te krijgen. Bv. - tempo 19 2x zo snel maken: 25-19=6. 6/2=3. 25-3=22. - -Tip 2: - - Als je gemaakte muziekstuk te kort is kun je dit heel erg - makkelijk rekken door bv. hetzelfde stuk nog eens af te - spelen zonder de melodie en (naar keuze) bas en/ of drums. - -Tip 3: - - Het maken van een muziekstuk gaat het makkelijkst als je - eerst een achtergrondje maakt met drums, bas, accoorden en - evt. special effects. Hierna hoef je alleen nog maar een - melodie toe te voegen, en klaar is Keessie ! - - -Tip 4: - - Je kunt een muziekstuk mooier maken als je tegelijkertijd - met het gewone achtergrondje ook een "pingel" laat meelopen. - De toonhoogte van deze pingel kun je het beste af laten - hangen van het accoord dat dan speelt. Een wel heel simpel - voorbeeld van een pingel: A 4 C 5 E 5 C 5. Natuurlijk zijn - er veel mooiere varianten denkbaar. Voor de pingel moet je - niet teveel afwijken van de noten van het accoord. - -Tip 5: - - Voor bijna alles uit deze (en voorgaande) afleveringen geldt - het volgende: het klinkt vaak mooi als je af en toe een - beetje variatie toebrengt door bepaalde noten ��n octaaf te - verhogen. - - Game Over - - Er zijn zo natuurlijk veel meer handige dingen te verzinnen, - maar ik heb geen zin om alles maar voor te kauwen, daar - wordt een mens maar lui van. Er is nog wel genoeg uit te - zoeken in de wondere wereld van MSX-muziek, maar dat moet je - dan zelf maar doen.... - - Dit is dan ook gelijk de afsluiting van deze MB-cursus. Alle - resultaten (waarschijnlijk geen) van deze cursus en eigen - probeersels zijn natuurlijk van harte welkom bij onze - FD-music contest (meer hierover in de Diversen-afdeling). - Als je onverhoopt nog vragen hebt (of wat anders) kun je me - bereiken op het volgende adres: - - Jorrith Schaap - Erasmusweg 7 - 9602 AB Hoogezand - Tel: 05980-27379 - - -Jorrith Schaap diff --git a/Future Disk/23/MCode Special 3.md b/Future Disk/23/MCode Special 3.md deleted file mode 100644 index f8f6041..0000000 --- a/Future Disk/23/MCode Special 3.md +++ /dev/null @@ -1,256 +0,0 @@ - - MCODE SPECIAL (3) - - - We gaan verder waar we op FD #21 waren blijven steken... - - -MAIN (het hoofdprogramma) - - Eigenlijk is dit de routine waaraan je het beste kunt - beginnen te programmeren. - Zorg dat de MAIN routine niet te lang wordt (zodat je hem in - ieder geval nog in 1 keer op het scherm kun krijgen) en zet - hier ook alleen de belangrijkste zaken in. - Je kunt dit bereiken door van elke onderdeel een CALL te - maken. Het is in het begin vaak al mogelijk om te zeggen wat - voor routines later in de hoofdroutine aangeroepen zullen - worden. Zet in de hoofdroutine dan alvast de CALL's klaar, - maak alvast de LABEL's aan maar zet op de plaats waar later - de eigenlijke routine komt een RET: dit bevordert het - overzicht, en bovendien blijf je op de hoogte van wat je - nog programmeren moet. De routine MAIN spreekt verder voor - zich: - -MAIN: - CALL SETSPRITES ; zet de sprites op goede coord. - EI - HALT - HALT - XOR A ; spatie balk ? - CALL GTTRIG - AND A - CALL Z,GEDRUKTQ ; misschien wel vuurknop - CALL NZ,GEDRUKT ; op knop gedrukt: maak zichtbaar - LD A,3 ; 2de knop ? - CALL GTTRIG - AND A - CALL Z,SHIFTQ ; misschien wel op shift - CALL NZ,VEILIG ; maak veilig - CALL BESTUUR ; besturingsroutines - CALL TESTEIND - LD A,7 - CALL SNSMAT - AND %00000100 ; escape - JP NZ,MAIN -EINDE: - XOR A - JP #5F - - Zoals je ziet kan met ESCape het spel afgebroken worden: dit - is een van de opties die je er het eerst in moet bouwen, - zodat je altijd uit het spel kan en kan controleren (als je - een programmeer fout maakt en de computer niets meer doet) of - je met ESCape nog weg kunt en het programma dus nog in de - hoofdlus rondliep. - - De spatiebalk en de linkermuisknop moeten er beide toe leiden - dat GEDRUKT aangeroepen wordt. Je test nu eerst op een van - beide (hier de spatiebalk) en als deze niet ingedrukt wordt - ( AND A levert zero ) test je in een aparte loop of de - linkermuisknop wel ingedrukt werd (GEDRUKTQ) - -GEDRUKTQ: - LD A,1 - CALL GTTRIG - AND A - RET - - p.s. de Q in sommige labels heeft voor mij de betekenis van - een ?, aangezien GEN80 labels met een ? niet aankan. - p.s.s. je ziet ook dat achter elk label een : geplaatst is. - Dit om het zoeken naar labels m.b.v. de TED-zoekfunctie - te vergemakkelijken, omdat je de aanroepplaatsen van - de labels niet tegenkomt. - - In de hoofdlus zitten ook nog 2 HALT's. - Deze zijn bedoeld om het geheel soepeler te laten verlopen. - Een hoofdlus zonder HALT duurt niet elke keer dat hij - doorlopen wordt even lang, b.v. omdat soms wel en soms niet - op een toets gereageerd moet worden. Dit heeft tot gevolg - dat b.v. de muisbesturing niet altijd even vaak per seconde - uitgevoerd wordt en de muis dus niet soepel loopt. - Zet daarom (als het even kan) altijd een of meerdere HALT's - in de hoofdlus. Het is verstandig om deze vooraf te laten - gaan door het commando: EI. - - Verder worden in de hoofdlus de routines BESTUUR en TESTEIND - altijd aangeroepen. VEILIG en GEDRUKT alleen als er op een - knop gedrukt wordt. De hooflus moet nooit te ingewikkeld - worden, anders verlies je het overzicht van het verloop van - het spel. - -BESTUUR - - In de routine BESTUUR wordt eerst de muis uitgelezen door - een aanroep van de subroutine MOUSE. - Je ziet in deze routine hoe dat er getest kan worden of er - een muis aangesloten is. - - M.b.v. de biosroutine GeTPAD worden in de adressen - #FAFE en #FB00 de verandering van de respectievelijk xco - en yco gezet. De inhoud van deze adressen wordt dan opgeteld - bij de huidige xco en yco van de 2 sprites, die staan op de - adressen aangeduid door de labels XCO en XCO+4(of YCO en - YCO+4) in de sprite-attribuuttabel. Zoals je ziet worden - hier nog niet deze attributen in het VRAM gezet, dat - gebeurt pas als in de hoofdlus opnieuw een CALL SETSPRITES - gebeurt. - Bovendien wordt m.b.v. het uitgebreid behandelde CP-commando - getest of het pijltje zich nog binnen de grenzen van het - beeld bevindt. - - Als de muisbesturing afgehandeld is, wordt gekeken of er - met de cursortoetsen of joystick bewogen wordt. - In het label SPEED staat hoeveel pixels er per druk op een - cursortoets verschoven wordt. - Normaal staat hierin 2 maar als de GRAPH-toets ingehouden - wordt, wordt dit getal 4. - - De Biosroutine GTSTCK levert de beweegrichting van cursor - of joystick. Aan de hand van deze waarde wordt bepaald welke - richtingsroutine aangeroepen wordt. - - Let er op dat voor een beweging in een diagonale richting - gewoon gebruik gemaakt wordt van de 2 bijbehorende - horizontale en vertikale richtingsroutines. - - Over de BESTUUR routine wil ik verder niet teveel uitwijden, - omdat deze niet bijster interessant is. Ik moet toegeven dat - ik bijna altijd als ik in een programma een besturings- - afhandeling nodig heb, ik deze routine (met enige aanpassing - van bv. de randcoordinaten) gebruik, omdat ze toch al zo - efficient mogelijk in elkaar zit. - Als je wil mag je gerust deze routine gebruiken in je eigen - programma's. Opnieuw programmeren is tijdsverspilling! - -LEES VERDER IN DEEL (2) - - MCODE SPECIAL (3) - - part 2 - - - -GEDRUKT (het spel zelf) - - We hebben nu een pijl, een veld met blokjes, besturingsroutines - en kunnen de knoppen uitlezen maar het spel zelf draait er - voornamelijk om dat er blokjes zichtbaar gemaakt kunnen worden. - De routine GEDRUKT regelt dit. - - GEDRUKT begint al meteen met een aanroep van een andere - routine: HAALBLOKNR. - - HAALBLOKNR zoekt uit op welk bloknr. het pijltje staat, - tevens worden DX en DY, de coordinaten waar naar toe straks - het blokje gekopieerd gaat worden al goed gezet. - -HAALBLOKNR: - LD A,(XCO) - AND %11110000 ; omlaag afronden - LD (DX),A ; wordt de plaats waar - een blok komt - RRCA - RRCA - RRCA - RRCA ; delen door 16: - het bloknr door xco - LD B,A ; even bewaren - LD A,(YCO) - AND %11110000 ; omlaag afronden - LD (DY),A ; is tevens bloknr. - door yco - ADD A,B ; optellen levert het - echte bloknr. - RET - - - In A staat nu het bloknummer, dit is dus de plaats in het - dataveld waarop gedrukt werd en die de speler van het spel - graag zichtbaar wil maken. Wij moeten nu laten zien wat er - op die plaats staat en hierop zonodig reageren. - Met de volgende routine komen erachter wat de gegevens (zie - bespreking DATAveld) zijn over het blokje waarop gedrukt - werd. - - - LD HL,DATA - LD C,A - LD B,0 ; nu in HL het DATA- - blokje, waarop je - ADD HL,BC ; met je pijlje hebt - gedrukt. - LD A,(HL) ; in A de inhoud van - je blok - - Bit voor bit wordt nu afgegaan wat die data voorstelt: - - BIT 5,A - RET NZ ; drukken op een vlag - heeft geen zin - BIT 6,A - RET NZ ; op een zichtbaar - blokje ook niet - BIT 7,A - JP NZ,DOOD ; op een mijn gedrukt - AND %00001111 - JP Z,CLEARDATA ; op een leeg hokje - - Een RET be�indigt de routine GEDRUKT, omdat deze met een - CALL aangeroepen wordt. Als je op een leeg hokje drukt wordt - doorverwezen naar een nieuwe routine, die de omgeving - automatisch zichtbaar gaat maken: CLEARDATA. Hierop ga ik - later in. Verreweg de meeste keren zal een speler drukken - op een getal dan moet het blokje zichtbaar gemaakt worden. - De hiervoor gegeven routine wordt dan gewoon doorlopen en - de computer komt aan bij de volgende routine: - -MAAKZICHTBAAR: - SET 6,(HL) ; in DATA aangeven - dat dit blokje al - LD HL,AANTALZICHTBAAR; zichtbaar is - INC (HL) - - Het aantal zichtbare hokjes wordt geteld, omdat we dan - eenvoudig kunnen nagaan of alle blokjes zichtbaar zijn. - Bovendien wordt in de data aangegeven, dat dit blokje nu - zichtbaar is zodat, als er nog een keer op dit blokje - gedrukt wordt, de computer niet meer reageert. - In het A register staan nu nog steeds de 4 onderste bit's - van de DATA. Dit is het getal wat afgedrukt moet worden. - Net zoals dit in de routine vulscherm gebeurde wordt de - Source Xcoordinaat als volgt berekend: - - ADD A,A - ADD A,A - ADD A,A - ADD A,A ; *16 bereken SX - LD (SX),A ; DX en DY al in - HAALBLOKNR gezet. - - DX en DY zijn al berekent, de rest van de gegevens ligt - vast --> met de volgende regels wordt het blokje - daadwerkelijk neergezet: - - LD HL,BLOKDATA ; laat ook zien waarop - gedrukt is - JP COPY ; einde GEDRUKT - - Na deze JP COPY wordt weer teruggekeerd naar de hoofdlus. - - Maar genoeg voor deze keer! De cursus gaat weer verder op de - volgende FD! Veel succes met programmeren! - -Ruud Gelissen - diff --git a/Future Disk/24/2+ Schermen.md b/Future Disk/24/2+ Schermen.md deleted file mode 100644 index de06fab..0000000 --- a/Future Disk/24/2+ Schermen.md +++ /dev/null @@ -1,149 +0,0 @@ - Ons aller lieve Tobias behandelt nog een keertje de MSX 2+ schermen .....stof voor de programmerende MSX 2+ freaks dus.... - - NOGMAALS: DE 2+ SCHERMEN. - - ���� - ���� - ���� - ���� - - - - Ik weet dat ik dit onderwerp al een keer eerder hab behan- - deld, maar bij gebrek aan andere onderwerpen toch nog maar - een keer de 2+ schermen. - - Ken je ze nog, de oude dagen waarin men net de 2+ over had - laten vliegen uit Japan; zonder handleiding uiteraard want - dan weegt het immers te veel. Daar komt nog eens bij dat de - handleiding geheel meestal in "onleesbare" Japanse "kriebels" - was zodat deze geen waarde had. Alles zelf uitzoeken was dus - het gevolg, en dan bleek al gauw dat de 2+ schermen - onhandelbaar waren. - In de oude dagen ja, want bij betere analyse blijkt namelijk - dat het allemaal nog wel meevalt, vooral screen 11 blijkt - helemaal niet zo onhandelbaar. Dat het allemaal wat meer - moeite kost, dat is wel zo... - -IN BASIC - - Deze idee�n waren natuurlijk toch wel ergens op gebaseerd, - in basic is er namelijk weinig mogelijk op de 2+ schermen. - COPY's en dergelijken gaan over het algemeen wel, maar - tekenen wordt toch een stuk moeilijker. Alleen met welgemik- - te VPOKE's is er het een en ander mogelijk. - In machinetaal is, mede door de hogere snelheid, al een stuk - meer mogelijk, en bij de juiste behandeling van de 2+ - schermen blijkt het allemaal toch nog mee te vallen. - -SCREEN 10 - - Dit is toch wel het meest gebruikte 2+ scherm in BASIC, des - te groter zal de verassing zijn als ik vertel dat dit scherm - helemaal niet bestaat. SCREEN 10 is een niet bestaande modus - die speciaal voor BASIC gemaakt is. De grap zit em namelijk - in het feit dat dit gewoon SCREEN 11 is maar door de BASIC - interpreter op een speciale manier wordt behandeld. Daardoor - zullen commando's als LINE en CIRCLE in SCREEN 10 wel goed - gaan. Verderop in deze tekst zal ik hierop terugkomen. - - -SCREEN 11 - - Zoals gezegd de eigenlijke modus van SCREEN 10. Dit scherm - bezit over een totaal aantal kleuren van 65536. Hoe ASCII ooit - aan die 12499 is gekomen weet ik niet, maar blijkbaar kunnen - ze beter programmeren dan tellen. Er worden per pixel 16 bits - gebruikt en bij mij levert dit nog altijd 65536 mogelijkhe- - den op als je zwart mee mag rekenen. In SCREEN 11 is, behalve - met welgemikte COPY's en VPOKE's, weinig spannends te doen. - Ook de VPOKE's zijn eigenlijk al alleen interressant in - ASSEMBLY omdat BASIC hier eigenlijk te sloom voor is. - - -SCREEN 12 - - Hier worden er 17 bits per pixel gebruikt wat 131072 kleuren - oplevert. Ook hier komt ASCII weer met een of ander vaag ge- - tal, dit keer 19268, maar ook daar klopt volgens mij geen - flikker van. Ook voor SCREEN 12 geldt weer hetzelfde, voor - de BASIC programmeurs niet echt spannend... - - -DE OPBOUW - - Zoals we al jaren van MSX gewend zijn moet alles zo moeilijk - en onhandig mogelijk zijn. Dus toen de 2+ standaard gemaakt - werd mocht het VRAM natuurlijk vooral niet groter worden, - nee!! Want dat zou handig zijn. Ook een snellere VDP was na- - tuurlijk uit den boze, kom nou! Maar men wilde natuurlijk - wel meer dan 256 kleurtjes. En dan moet je dus gaan rommelen - zoals ze bij ASCII gedaan hebben. - Om toch meer kleurtjes in dezelfde hoeveelheid VRAM te - proppen werd er dus besloten om van elke 4 pixels een aantal - bits (12) gemeenschappelijk te gebruiken. Op deze manier kon - er voor elke 4 pixels een basiskleur worden ingesteld. - Vervolgens kon voor elke pixel afzonderlijk een helderheid - worden ingesteld. Hoe dit werkt zie je in het volgende - schemaatje. - - - BIT7 BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 BIT0 - PIXEL0 HE HE HE HE HE GR GR GR - PIXEL1 HE HE HE HE HE BL GR GR SCREEN 12 - PIXEL2 HE HE HE HE HE RO RO RO - PIXEL3 HE HE HE HE HE BL RO RO - - BIT7 BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 BIT0 - PIXEL0 HE HE HE HE PA GR GR GR - PIXEL1 HE HE HE HE PA BL GR GR SCREEN 11 - PIXEL2 HE HE HE HE PA RO RO RO - PIXEL3 HE HE HE HE PA BL RO RO - - HE:Helderheid RO:Rood GR:Groen BL:Blauw PA:Palet - - - Zoals verwacht heeft SCREEN 12 een andere opbouw dan scherm - modus 11. Alle bits voor Rood Groen en Blauw worden voor de - betreffende pixels gebruikt als basiskleur. Vervolgens kan - er met de 5 HE-bits de helderheid per pixel worden ingesteld - zonder dat dit van invloed is op de andere 3 pixels. - Bij SCREEN 11 echter, zijn er maar 4 Helderheids bits per - pixel beschikbaar. En hierin schuilt dus de grap waar BASIC - gebruik van maakt in screen 10. Het derde bitje, waar PA - staat, is namelijk een switch die van PAlet verwisseld. - Er wordt hier namelijk gekozen tussen het standaard palet - zoals we dat in SCREEN 5 kennen, en het palet dat SCREEN 11 - zelf gebruikt. Is het bit laag, dan wordt de kleur-methode - van SCREEN 11 gehanteerd, en de SCREEN 5-palet mode. Waarom - ASCII speciaal hiervoor in BASIC een tiende scherm heeft - gemaakt weet ik niet, volgens mij hadden ze dit net zo goed - in SCREEN 11 kunnen doen, maar ja, van jongens die niet eens - kunnen tellen moet je natuurlijk niet te veel verwachten. - - - Verder valt er eigenlijk weinig te zeggen over deze screens. - Je weet nu waar wat staat, pas op met COPY's, hou de coordi- - naten wel in een viervoud. En dat is eigenlijk wel zo'n - beetje wat er te vertellen is. - - Ter illustratie van het geheel heb ik nog even een klein MC - programmaatje geschreven voor de V9958. Als het goed is staat - SCREEN12.BIN wel op de disk. Dit programmaatje zet de eerste - 65536 kleuren van SCREEN 12 op het scherm waarna je met cur- - sor up & down nog door het geheel heen kan scrollen, anders - mis je de laatste 44 lijnen. Het programmaatje zet 32 tinten - rood, gemengd met 32 tinten groen en 2 tinten blauw op het - scherm in de 32 aanwezige helderheden. Dit geeft: - 32x32x2x32=65536 van de 32x32x4x32=131072 aanwezige kleuren - als we er tenminste van uit gaan dat ik geen fouten heb ge- - maakt, wat opzich vrij onlogisch zou zijn. Een snelheids - wonder is het niet, in R800 mode kost het zo'n seconde of 3 - om de kleurtjes op het scherm te plaatsen en in Z80 mode een - seconde of zes. Daarna mag je er lekker op los scrollen met - 60 pixels per seconde... Oh joy!! - -Geluk d'r mee... - -Keizer - diff --git a/Future Disk/24/V9958 in ML.md b/Future Disk/24/V9958 in ML.md deleted file mode 100644 index 05c65df..0000000 --- a/Future Disk/24/V9958 in ML.md +++ /dev/null @@ -1,79 +0,0 @@ - Ons liever Tobias heeft zich flink uitgesloofd, dus alweer een tekst van deze plezante zeer aardige en lieve jongen uit Nijverdal, bellen meiden, hij is nog vrij! - -V9958 in ML - - ���� - ���� - ���� - ���� - - - Ook dit heeft geloof ik al een keer eerder op de FD gestaan, - maar omdat ik weer over SCREEN 12 in basic begon toch nog een - keer de ML versie van SCREEN 12. - - Als eerste is het natuurlijk handig om te weten of de V9958 - wel aanwezig is. Ik persoonlijk kijk hier eigenlijk niet - eens naar. Als je zo dom bent om een 2+ programma op een - MSX 2 te runnen moet je natuurlijk niet vreemd opkijken als - het dan niet werkt. Maar soms kan het voorkomen dat je echt - ��n aparte routine voor de MSX2 en de MSX2+ hebt en dan is - het natuurlijk wel handig om te weten of de V9958 wel - aanwezig is. Dus eerst even een klein stukje assembly: - - CHKVDP: DI - LD A,$01 - OUT ($99),A - LD A,$8F - OUT ($99),A - PUSH AF - POP AF - IN A,($99) - LD D,A - XOR A - OUT ($99),A - LD A,$8F - OUT ($99),A - EI - JP_RTN: LD A,D - AND $3E - JP NZ,V_9938 - JP V_9958 - - Vervolgens is het misschien wel handig om SCREEN 12 aan te - zetten. Als je graag wilt mag je van mij SCREEN11 ook wel - aanzetten hoor! Okay, here we go: - - SCRN11: LD A,$08 - CALL $5F - DI - LD A,$18 - OUT ($99),A - LD A,$99 - OUT ($99),A - EI - - SCRN12: LD A,$08 - CALL $5F - DI - LD A,$08 - OUT ($99),A - LD A,$99 - OUT ($99),A - EI - - En dit zou toch echt moeten werken want mijn SCREEN12.BIN op - deze FD gebruikt dit stukje code ook. - - Dit is overigens ook handig voor het BASIC volk dat de MSX2+ - commando's i.v.m. compatibiliteit met de MSX2's met een - V9958 in stand wil houden. Gewoon intypen in WB, assembleren - en de .BIN file BLOADen aan het begin van je programmaatje. - - Hey guys, guess what?! It's 02.19 and I'm tired. Sleep well - and see you in the morning. I'm gonna have sweet dreams - about Amalia now.... - -Dikke zoen, - -Keizer... diff --git a/Future Disk/25/Clock chip.md b/Future Disk/25/Clock chip.md deleted file mode 100644 index 378c1dc..0000000 --- a/Future Disk/25/Clock chip.md +++ /dev/null @@ -1,154 +0,0 @@ - CURSUS CLOCK-KIJKEN, de clock-chip nader bekeken. - ================================================= - - ���� - ���� - ���� - ���� - - - Dat de clock-chip in de MSX gebruikt wordt om de tijd in bij - te houden, zullen de meeste mensen wel kunnen gokken, maar er - schuilt heel wat meer achter die "32 bytes S-RAM". - -DE TIJD - - De tijd, want dat is toch waarvoor men de klokchip meestal - zal gebruiken. In BASIC is dat niet zo'n probleem, een - simpele GET TIME helpt de BASIC-er wel aan de juiste tijd, ter- - wijl onder een DOS omgeving een BDOS call naar $002C ook het - probleem wel uit de wereld helpt. In een BASIC omgeving - wellicht makkelijk, maar in machinetaal wordt het echter al - een stuk moeilijker, tenzij men natuurlijk naar dezelfde BDOS - call grijpt, maar hoe zit het eigenlijk met alle andere infor- - matie in de clock-chip?? - -DE OPBOUW - - De opbouw van de clock-chip doet ietwat vreemd aan, in de - eerste plaats staat de data al niet in echt S-RAM, en is het - geheel niet opgedeeld in bytes, hetgeen de aanhalingstekentjes - in de inleiding verklaart. Eigenlijk is de clock-chip verdeeld - in 4 blokken van 16 vierbits registers. Nybble werk dus, YUK!! - - Gelukkig voorziet het BIOS in een routine om de clock-chip uit - te lezen, hetgeen de minder ervaren programmeurs weer een paar - uur scheelt. Dus, 64 nybbles om alle data in op te slaan, maar - waar staat dan wat? Dat was het eerste probleem waar ik op - stuitte bij mijn speurtocht door de clock-chip. Over de eerste - twee blokken, die voor de tijd & datum gebruikt worden, was - nog wel informatie te vinden. Over de laatste twee blokken - echter, was niets te vinden. Nu is het ongetwijfeld zo dat wel - in een of ander technical-databook deze informatie staat, maar - via 'normale' wegen, bleek het niet makkelijk om deze informa- - tie te achterhalen. Mij is dit dan ook alleen gelukt via het - befaamde "trial & error" proces, waarbij de nadruk toch wel op - error lag... - -NYBBLE WERK... - - Vierenzestig nybbles dus, die via de de BIOS routine $01F5 uit - de SUB-ROM te lezen zijn. De nybbles waarin de data staat bom- - barderen we maar even tot registers, en dan zijn er dus nog de - vier blokken die te selecteren zijn. De eerste twee blokken wa- - ren dus voor de tijd en datum, de overige twee voor de instel- - lingen van BASIC. Als invoer heeft de BIOS routine in register - C "twee variabelen" nodig. In bit 4 & 5 van register C staat - welk blok we wensen te lezen, 0-3 dus. In bit 0-3 staat dus - het registernummer 0-15. Als output komt de routine met in reg - A het gelezen nybble. De laaste 4 bits dienen genegeerd te - worden. Maak deze dus maar voor het gemak 0. En dan nu dus de - tabel, die ik zoals gezegd heb moeten uitvogelen door domweg - wat te proberen. Van 3 reg's ben ik niet te weten gekomen wat - hun functie is, en de laatste 3 registers zijn voor intern ge- - bruik waar men dus niets aan heeft. Het enige dat ik er van - weet is dat het respectievelijk de MODE, TEST en RESET regis- - ters zouden moeten zijn, hun functie is mij onduidelijk. - - - REG �V block 0 �V BLOCK 1 �V BLOCK 2 �V BLOCK 3 �V - �W�W�W�W�W�W�W�W�U�W�W�W�W�W�W�W�W�W�W�W�W�U�W�W�W�W�W�W�W�W�W�W�W�W�U�W�W�W�W�W�W�W�W�W�W�W�W�U�W�W�W�W�W�W�W�W�W�W�W�W�S - $00 �V SEC 2 �V ONGEBRUIKT �V -ONBEKEND- �V STRING I.D �V - $01 �V SEC 1 �V ONGEBRUIKT �V ADJUST X �V CHR0 LN �V - $02 �V MIN 2 �V MIN 2 (AL) �V ADJUST Y �V CHR0 HN �V - $03 �V MIN 1 �V MIN 1 (AL) �V -ONBEKEND- �V CHR1 LN �V - $04 �V UUR 2 �V UUR 2 (AL) �V WIDTH LN �V CHR1 HN �V - $05 �V UUR 1 �V UUR 1 (AL) �V WIDTH HN �V CHR2 LN �V - $06 �V DAG V WEEK �V DAG V WEEK �V VOOR KLEUR �V CHR2 HN �V - $07 �V DAG 2 �V DAG 2 (AL) �V ACHT KLEUR �V CHR3 LN �V - $08 �V DAG 1 �V DAG 1 (AL) �V RAND KLEUR �V CHR3 HN �V - $09 �V MAAND 2 �V ONGEBRUIKT �V SCREEN SET �V CHR4 LN �V - $0A �V MAAND 1 �V 12/24 UURS �V "BEEP"INFO �V CHR4 HN �V - $0B �V JAAR 2 �V SCHRIKKELJ �V LOGO KLEUR �V CHR5 LN �V - $0C �V JAAR 1 �V ONGEBRUIKT �V -ONBEKEND- �V CHR5 HN �V - $0D �V MODE------ �V MODE------ �V MODE------ �V MODE------ �V - $0E �V TEST------ �V TEST------ �V TEST------ �V TEST------ �V - $0F �V RESET----- �V RESET----- �V RESET----- �V RESET----- �V - �W�W�W�W�W�W�W�W�U�W�W�W�W�W�W�W�W�W�W�W�W�U�W�W�W�W�W�W�W�W�W�W�W�W�U�W�W�W�W�W�W�W�W�W�W�W�W�U�W�W�W�W�W�W�W�W�W�W�W�W�S - - - Ervaren ML-programmeurs kunnen hiermee uit de voeten, voor - het geval dat er echter nog het een en ander onduidelijk is - zal ik alles even apart behandelen. - - -NOG EENS DE TIJD - - Zoals in de tabel te zien is komen sommige variabelen voor - met een 1 en een 2 erachter. Dit zijn dus Binairy Coded Deci- - mals. Voor diegenen die niet weten wat dit inhoud; Gewoon het - eerste getal, dat het tweede cijfer voorstelt, met 10 verme- - nigvuldigen en de andere nybble erbij optellen. Overal waar - LN en HN staat bedoel ik HighNybble en LowNybble, wat dat in- - houd behoeft naar ik aanneem geen uitleg. Van de registers - waar -ONBEKEND- staat heb ik simpelweg de functie niet van - kunnen achterhalen.Mocht iemand wel weten waar deze registers - (paren) voor dienen, of mocht iemand andere onvolkomendheden - in de tabel ontdekken, dan wordt het zeer op prijs gesteld - als die persoon ons hiervan op de hoogte stelt. -Xela?- - (NvdR: en jij optimist meent dat daar iemand op reageert?) - -ANDERE OPSLAG METHODEN - - Een uitzondering is bijvoorbeeld al het jaartal, dit wordt ge - vormd door (JAAR2*10)+8 en de andere nybble. De offset voor - het jaar is dus eigenlijk 1980. - - Dag v week is simpelweg de dag van de week. - - 12/24Uurs geeft aan of de 12uurs klok of de 24uurs klok door - de gebruiker is ingesteld. - - Schrikkelj is een tellertje voor intern gebruik waar wordt - bijgehouden of we wel of niet met een schrikkeljaar te maken - hebben. Deze is overigens 2 bits lang. - - De ADJUST X & Y zijn de waarden die we in BASIC met het SET - ADJUST commando kunnen instellen. Hierbij gaat het om 2-compl - nybbles. - - De registers WIDTH tm RAND KLEUR spreken voor zich. - - Dan komt er een register dat volledig uit losse bits is opge- - bouwd. Bit0: Functie toesten (0:uit 1:aan ) - Bit1: Key Klick (0:uit 1:aan ) - Bit2: Type printer (0:MSX 1:IBM ) - Bit3: Standaard Baudrate (0:1200 1:2400) - Bij gebrek aan een betere naam noem ik dit maar "SCREEN SET". - - Dan het register met de BEEP informatie: Bit 0-1: Type BEEP - Bit 2-3: Volume /4 - - Vervolgens het register dat de kleur van het MSX-logo bij de - reset routine representeerd. - - Het register dat ik STRING-ID heb genoemd heeft betrekking op - de daarop volgende registers. STRING-ID bepaald de functie - van de daarop volgende STRING. De STRING kan namelijk PROMPT, - TITLE & PASSWORD zijn. Bij resp. 1,0 & 2 voor STRING-ID. - - De rest van de registers zijn dus gereserveerd voor de STRING - die door STRING-ID een functie had gekregen. - - En dan hebben we zo'n beetje alle registers gehad. Waarmee de - clock-chip dus ook zo'n beetje afgehandeld zou mo diff --git a/Future Disk/25/MCode Special 4.md b/Future Disk/25/MCode Special 4.md deleted file mode 100644 index bbd51f4..0000000 --- a/Future Disk/25/MCode Special 4.md +++ /dev/null @@ -1,282 +0,0 @@ - - MCODE SPECIAL (4) - - part 1 - - - We gaan verder met deze zeer special cursus... - - VEILIG (de routine die een vlag plaats/weghaald) - - Als je op SHIFT drukt moet de computer een vlag plaatsen, - stond er echter al een vlag wil je graag dat deze weggehaald - wordt. De snelheid van de machinetaal levert dit keer een - probleem op: als de speler 1 keer op SHIFT gedrukt denkt te - hebben is onze hoofdlus vaak meerdere keren (soms wel 4) door- - lopen, hetgeen tot gevolg heeft dat je de vlag aan en uit - ziet flikkeren i.p.v. netjes omwisselen. Je kunt dit voorkomen - m.b.v de volgende routine, die je moet plaatsen voordat - op de toets gereageerd wordt: - - LD A,(VORIGSHIFT) ; als de vorige keer shift al - AND A ; ingedrukt was, nu niet meer - RET NZ ; reageren (voorkomen van: aan/uit) - INC A ; wordt 1 (dus NotZero) - LD (VORIGSHIFT),A ; volgende keer niet reageren - - Als er nu op SHIFT gedrukt wordt, wordt dit opgeslagen in het - label VORIGSHIFT(er staat 1 in). - Zodra nu de volgende keer weer op SHIFT wordt gedrukt (door - te lang inhouden) wordt dit geblokkeerd door de RET NZ. - Als SHIFT losgelaten wordt moet VORIGESHIFT natuurlijk wel - weer op nul gezet worden, omdat je anders maar 1 vlag kan - plaatsen per spel. - - Als er op Shift gereageerd moet worden vindt eerst weer een - aanroep van de routine die eerder beschreven werd: - - CALL HAALBLOKNR ; in A komt bloknr. - - In A staat nu het bloknummer, dit is dus de plaats in het - dataveld waarop gedrukt werd en waarop de speler een vlag wil - plaatsen. Net als in de routine GEDRUKT wordt eerst weer geke- - ken of je op deze plaats wel een vlag mag plaatsen: - - LD HL,DATA - LD C,A - LD B,0 ; nu in HL het DATA-blokje, - ADD HL,BC ; waarop je stond. - BIT 6,(HL) ; al zichtbaar ? - RET NZ ; ja: geen vlag - - Dan wordt onderzocht of er een vlag geplaatst moet worden of - weggehaald moet worden: - - BIT 5,(HL) ; was het al een vlag ? - JR Z,NUVLAG ; we plaatsen een vlag - RES 5,(HL) ; weg met de vlag - LD A,144 ; Source Xco van Onzichtbaar blokje - LD (SX),A - LD HL,BLOKDATA ; laat ook zien. - JP COPY ; einde VEILIG - - Als de vlag weggehaald moets worden wordt er een onzichtbaar - blokje overheen geplaatst en in het dataveld aangegeven dat - de vlag weg is. Moest de vlag geplaatst worden volgt de - volgende routine: - -NUVLAG: - SET 5,(HL) ; Zet DATAblokje op vlag. - LD A,160 ; Source Xco van vlag - LD (SX),A ; DX en DY al in HAALBLOKNR - gezet - LD HL,BLOKDATA ; laat ook een vlag zien. - JP COPY ; einde VEILIG - - -TESTEIND (testen of je gewonnen bent) - - Testen of alles zichtbaar is wat zichtbaar moet zijn, komt er - op neer door te kijken of het aantal zichtbare blokjes (dat we - in GEDRUKT geteld hebben) + het aantal mijnen (dat vast ligt) = - het aantal blokjes op het scherm (16*13). De volgende routine - doet dat: - -TESTEIND: LD A,(AANTALMIJNEN) ; als alle blokjes die - geen mijn zijn - LD B,A - LD A,(AANTALZICHTBAAR) ; zichtbaar zijn - ADD A,B - CP MAXBLOKJES ; heb je gewonnen. - RET NZ - LD A,1 - LD (EINDBT),A - jp #c0 - RET - - Merk op dat er, omdat deze routine in de hoofdlus (altijd) - wordt aangeroepen, nu een onafgebroken rij BEEP's klinken als - je gewonnen hebt. - Als je wilt kun je in de hoofdlus een test op EINDBT toevoegen, - die springt naar een soort van einddemo, maar ik vind dit niet - interessant genoeg om zoiets te gaan programmeren (lees: ik - ben hier te lui voor) (aangezien ene K.Dols er toch niet aan - begint deze tekst te lezen verwacht ik hier geen N.V.D.R ..... - of toch??.....)(NvdR: Gaap gaap). - - Zo, het spel is nu in principe klaar en kan al gespeeld wor- - den, maar we willen nog graag dat het drukken op een leeg - hokje een soort kettingreactie van zichtbaar maken tot gevolg - heeft. Hoe kun je nu zoiets bereiken ? - Als een leeg hokje zichtbaar wordt gemaakt, wordt naar de - routine CLEARDATA gesprongen. - In deze routine wordt linksboven op het scherm begonnen met - kijken of er een leeg hokje staat (in praktijk wordt in het - DATAveld gekeken). - Zolang als er geen leeg hokje wordt gevonden wordt er 16 bij - de xco opgeteld tot het einde van de regel bereikt wordt. - Dan wordt er 16 bij de yco opgeteld en weer begonnen op - xco=0 ect. tot het einde van het scherm (en DATAveld) bereikt - is. - Als er wel een leeg hokje gevonden wordt, wordt er doorge- - sprongen naar de routine DOCLEAR. - In DOCLEAR gebeurt het eigenlijke zichtbaar-maak-werk. Als er - een hokje zichtbaar gemaakt wordt, wordt de teller FOUND - verhoogd. De routine wordt dan nogmaals herhaald (dus het hele - scherm wordt opnieuw onderzocht naar e.v. (nieuwe, maar ook - oude) lege hokjes: dit is dus de kettingreactie. - Als er tenslotte geen nieuwe hokjes zichtbaar gemaakt worden, - wordt de routine VULSCHERM aangeroepen, die het hele scherm - opnieuw vult met blokjes. - - Dat regelt de volgende routine: - - Welke routine? Zie voor deze routine tekst (2)! - - MCODE SPECIAL (4) - - part 2 - - - En we gaan verder met die routine: - - CLEARDATA: - CALL MAAKZICHTBAAR ; maak het lege hokje - ; zichtbaar - CLEARREPEAT: ; naar dit label wordt teruggesprongen als er - ; hokjes zichtbaar gemaakt zijn: deze kunnen leeg - ; zijn => herhaal - LD B,MAXBLOKJES - LD HL,DATA - XOR A ; begin linksboven - LD (XCO1),A ; om alle coordinaten te door- - ; lopen en te kijken welke - LD (YCO1),A ; blokjes rondom staan - CLEARDATALOOP: - PUSH HL - PUSH BC - LD A,(HL) - CP ZICHTBAARLEEG ; =&B01000000 - CALL Z,DOCLEAR - POP BC - POP HL - INC HL - LD A,(XCO1) ; verhoog xco tot einde - ADD A,16 ; beeldscherm steeds met 16 => - ; volgend blokje - CALL Z,YHOGER ; als xco=256 dan is xco 0: - ; verhoog yco - LD (XCO1),A - DJNZ CLEARDATALOOP - - - LD A,(FOUND) ; is er een blokje zichtbaar - AND A ; gemaakt - JP Z,VULSCHERM ; nee, sluit af met opbouw - ; van hele scherm. - XOR A ; begin opnieuw : nog niks zichtbaar - ; gemaakt - LD (FOUND),A - JP CLEARREPEAT ; en herhalen tot alles - ; zichtbaar is - - YHOGER: LD A,(YCO1) - ADD A,16 - LD (YCO1),A - XOR A ; xco op 0 - RET - - Als we in DOCLEAR aankomen weten we zeker dat in XCO1 en YCO1 - de coordinaten staan van het lege blokje. Rondom deze coordinaten - moeten we dus gaan kijken. Als het blokje geen rand-blokje is - zijn er 8 plaatsen rondom. In HL staat het adres in het DATA - veld waar het lege blokje zich bevindt. - Er moet dan gekeken worden op de volgende adressen: - - HL-17: linksboven het lege blokje - HL-16: recht er boven - HL-15: rechtsboven - HL-1: links - HL+1: rechts - HL+15: linksonder - HL+16: recht er onder - HL+17: rechtsonder - - Als het blokje zich bevindt aan ��n van de randen (of in de - hoeken) moeten er minder geheugenadressen in het DATAveld - onderzocht worden. We kunnen de volgende data aanmaken: - - - ;---- Rondtedata's: Geven aan hoeveelbyte verder/terug de - ; blokjes staan, die rondom een leeg hokje zitten. - ; Eerste byte is aantal blokjes = aantal bytes in die - ; rondtedata. - - DATAMIDDEN: DB 8,-17,-16,-15,-1,1,15,16,17 - DATALINKS: DB 5,-16,-15,1,16,17 - DATARECHTS: DB 5,-17,-16,-1,15,16 - DATABOVEN: DB 5,-1,1,15,16,17 - DATAONDER: DB 5,-17,-16,-15,-1,1 - DATALB: DB 3,1,16,17 - DATARB: DB 3,-1,15,16 - DATALO: DB 3,-16,-15,1 - DATARO: DB 3,-17,-16,-1 - - Om te weten welke Rondtedata gebruikt moet worden, moeten we - eerst weten waar het blokje zich op het scherm bevindt: - n.l. aan ��n van de randen of in ��n van de hoeken of ergens - in het midden. - - Dit wordt onderzocht in de routine ZOEKRONDTEDATA. - - ZOEKRONDTEDATA: - LD A,(XCO1) - CP 16 - JR NC,NIETLINKS - LINKS1: LD A,(YCO1) - CP 16 - JR NC,NIETBOVEN1 - LINKSBOVEN: LD DE,DATALB - RET - NIETLINKS: CP 15*16 - JP C,NIETRECHTS - RECHTS1: LD A,(YCO1) - CP 16 - JR NC,NIETBOVEN2 - RECHTSBOVEN: LD DE,DATARB - RET - NIETBOVEN1: CP MAXBLOKJES-16 ; onderrand dataveld - ; (laatste regel) - JR C,LINKSMID - LINKSONDER: LD DE,DATALO - RET - LINKSMID: LD DE,DATALINKS - RET - NIETRECHTS: LD A,(YCO1) - CP 16 - JR NC,NIETBOVEN - BOVEN1: LD DE,DATABOVEN - RET - NIETBOVEN: CP MAXBLOKJES-16 ; idem - JR C,MIDDEN - ONDER1: LD DE,DATAONDER - RET - MIDDEN: LD DE,DATAMIDDEN - RET - NIETBOVEN2: CP MAXBLOKJES-16 ; idem - JR NC,RECHTSONDER - RECHTSMID: LD DE,DATARECHTS - RET - RECHTSONDER: LD DE,DATARO - RET - - Deze routine is niet bijster interessant en ook niet zo leuk - om te schrijven, maar ze werkt en heeft tot resultaat dat er - in DE, de juiste Rondtedata komt te staan. - - Maar dan...plotseling een eind aan deze tekst: - - Op de volgende FD het allerlaatste deel van deze zeer interes- - sante cursus! - -Ruud Gelissen diff --git a/Future Disk/25/MSX-DOS2 deel 1.md b/Future Disk/25/MSX-DOS2 deel 1.md deleted file mode 100644 index 1d5396b..0000000 --- a/Future Disk/25/MSX-DOS2 deel 1.md +++ /dev/null @@ -1,193 +0,0 @@ - MSX-DOS2, deel 1 - - ���� - ���� - ���� - ���� - - -Waar moet dat heen met de FD?! - - Kreeg ik toch laatst zomaar een brief van een lezer, HELP!?! - Hoe kan dit?!? Wat moet dat! Kom nou, FD-leden schrijven geen - brieven!! Nou ja, uit deze aangename verrassing blijkt dat er - toch nog FD leden zijn die zo nu en dan eens een keertje een - briefje durven te schrijven. Om deze pen-vriend te beschermen - zal ik zijn identiteit niet prijsgeven. Neen, deze held mag - anoniem blijven. - -MSX-DOS 2 - - Want daar ging de brief namelijk over, hoe onze vriend met MSX - DOS 2 kon werken in assembly, de calls dus... En als de FD een - brief over een onderwerp ontvangt, dan moet dat wel iets HEEL - belangrijks zijn. Vandaar dat ik naast de brief die onze held - inmiddels heeft ontvangen, ook nog een stukje op de FD aan die - onzin wil wijden. Ik meende zelf dat DOS2 eigenlijk een open - boek was, maar blijkbaar zijn er toch nog mensen die hier nog - wel 't een en ander over willen weten. Daar gaan we dus... - - -DOS2 in BASIC - - Ik weet niet hoe het bij de andere MSX-en zit, maar bij de MSX - Turbo-R [DOS2.30] is het zo dat de BASIC programmeur nog een - aantal extra commando's tot zijn beschikking heeft. Door - gebrek aan documentatie ken ik deze niet allemaal, maar een - aantal ken ik er toevalling uit m'n hoofd. Okay... - - CALL RAMDISK (xx) > Maak een ramdisk van [xx] kB aan. - - CALL CHDRV ("x:") > Maak van [x] de default drive. - - CALL CHDIR ("xx") > Ga naar directory [xx] (zoals DOS) - Hierbij behoren "\" & ".." ook tot - de mogelijkheden. - - CALL MKDIR ("xx") > Maak directory aan, als CHDIR. - - CALL RMDIR ("xx") > Verwijder directory, als CHDIR. - - Het zal best dat er nog meer commando's mogelijk zijn, maar ik - ken ze niet. Mocht iemand wel meer informatie hebben dan wordt - een belletje altijd gewaardeerd. Tot zover BASIC, nu naar het - echte werk, DOS2 in ML. - - -MSX-DOS2 in Assembly langue. - - Ik wil hier verder niet al te diep op ingaan, simpelweg een - beschrijving van de DOS2 calls, gewijzigde registers en input - & output registers. That's it! Hou er dus rekening mee dat - alle registers gewijzigd worden als ze al niet als output re- - gister dienen. Eerst de zooi PUSHen dus. DOS1 voor de call - betekent dat de routine DOS1 compatible is, anders dus NIET. - Here it goes... - - Kort overzicht: - - $00 [DOS1] Bye Bye! - $01 [DOS1] Console in - $02 [DOS1] Console out - $03 [DOS1] Aux in - $04 [DOS1] Aux out - $05 [DOS1] Printer out - $06 [DOS1] Direct console I/O - $07 [DOS1] Direct console in - $08 [DOS1] Console in without echo - $09 [DOS1] String out - $0A [DOS1] Buffered line in - $0B [DOS1] Console status - $0C [DOS1] DOS version - $0D [DOS1] Disk reset - $0E [DOS1] Select disk - $0F [DOS1] Open file FCB - $10 [DOS1] Close file FCB - $11 [DOS1] Search first FCB - $12 [DOS1] Search next FCB - $13 [DOS1] Delete file FCB - $14 [DOS1] Sequential read FCB - $15 [DOS1] Sequential write FCB - $16 [DOS1] Create file FCB - $17 [DOS1] Rename file FCB - $18 [DOS1] Get login vector - $19 [DOS1] Get current drive - $1A [DOS1] Set Disk transfer address - $1B [DOS1] Get allocation info - $1C [----] N.U. - $1D [----] N.U. - $1E [----] N.U. - $1F [----] N.U. - $20 [----] N.U. - $21 [DOS1] Random read FCB - $22 [DOS1] Random write FCB - $23 [DOS1] Get file size FCB - $24 [DOS1] Set random record FCB - $25 [----] N.U. - $26 [DOS1] Random block write FCB - $27 [DOS1] Random block read FCB - $28 [DOS1] Random zero fill FCB - $29 [----] N.U. - $2A [DOS1] Get date (Though I prefer to use Roses) - $2B [DOS1] Set date Hmmm, almost funny �W�W�W�W�[ - $2C [DOS1] Get time - $2D [DOS1] Set time - $2E [DOS1] -re-set verify flag - $2F [DOS1] Sector read - $30 [DOS1] Sector write - - $31 [DOS2] Get disk parameters - $32 [----] N.U. - $33 [----] N.U. - $34 [----] N.U. - $35 [----] N.U. - $36 [----] N.U. - $37 [----] N.U. - $38 [----] N.U. - $39 [----] N.U. - $3A [----] N.U. - $3B [----] N.U. - $3C [----] N.U. - $3D [----] N.U. - $3E [----] N.U. - $3F [----] N.U. - $40 [DOS2] Find first entry - $41 [DOS2] Find next entry - $42 [DOS2] Find new entry - $43 [DOS2] Open file handle - $44 [DOS2] Create file handle - $45 [DOS2] Close file handle - $46 [DOS2] Ensure file handle - $47 [DOS2] Dupe file handle - $48 [DOS2] Read from file handle - $49 [DOS2] Write to file handle - $4A [DOS2] Move file handle pointer - $4B [DOS2] Device I/O control - $4C [DOS2] Test file handle - $4D [DOS2] Delete file/dir - $4E [DOS2] Rename file/dir - $4F [DOS2] Move file/dir - $50 [DOS2] Set/Get file attributes - $51 [DOS2] Set/Get file time//date - $52 [DOS2] Delete file handle - $53 [DOS2] Rename file handle - $54 [DOS2] Move file handle - $55 [DOS2] Set/Get file handle attributes - $56 [DOS2] Set/Get file handle date//time - $57 [DOS2] Get disk transfer address - $58 [DOS2] Get verify flag - $59 [DOS2] Get current dir - $5A [DOS2] Change dir - $5B [DOS2] Parse pathname - $5C [DOS2] Parse filename - $5D [DOS2] Check character - $5E [DOS2] Get whole path string - $5F [DOS2] Flush disk buffers - $60 [DOS2] Fork a child process - $FD [DOS6] Spoon an adult process - $61 [DOS2] Rejoin parent process <- T'is net spoorloos - $62 [DOS2] Terminate with error code - $63 [DOS2] Define abort exit routine - $64 [DOS2] Define disk error handler routine - $65 [DOS2] Get previous error code - $66 [DOS2] Explain error code - $67 [DOS2] Format a disk - $68 [DOS2] Ramdisk settings - $69 [DOS2] Allocate sector buffers - $6A [DOS2] Logical drive assignment - $6B [DOS2] Get environment item - $6C [DOS2] Set environment item - $6D [DOS2] Find environment item - $6E [DOS2] Set/Get disk check status - $6F [DOS2] Get DOS version - $70 [DOS2] Set/Get redirection status - - - Hoppa, da's een hele lijst. Maar dan wel een lijst waar je - niets aan hebt. Voor de calls moet je uiteraard ook de - specifieke gegevens hebben. En laat ik nou net zo aardig zijn - om die je niet te geven... Sorry, geen tijd meer. Volgende FD! - - -Tobias "Gna, gna, gna" Keizer - diff --git a/Future Disk/27/Mcode Special 5.md b/Future Disk/27/Mcode Special 5.md deleted file mode 100644 index d324b33..0000000 --- a/Future Disk/27/Mcode Special 5.md +++ /dev/null @@ -1,119 +0,0 @@ - Ruud bespreekt het laatste stukje uit zijn Minesweeper source... - - MCODE CURSUS (5) - - - We gaan weer verder... - - We weten nu hoeveel adressen onderzocht moeten worden en welke - adressen dat zijn (we weten n.l. hun Offset t.o.v. het adres - van het lege blokje). In HL staat nog steeds het adres van het - lege blokje. Het onderzoeken van de adressen van de blokjes - eromheen gebeurt nu met de volgende routine: - - DOCLEAR: - LD A,(DE) ; aantal plaatsen rondom - LD B,A ; die ev. nog zichtbaar moeten worden - DOCLEARLOOP: PUSH HL - PUSH BC - INC DE - LD B,0 - LD A,(DE) ; offset (in geheugenplaatsen) - BIT 7,A - CALL NZ,NEGATIEF - LD C,A ; t.o.v. het lege blokje - ADD HL,BC ; optellen bij adres lege blokje - BIT 6,(HL) - CALL Z,ZICHTBAAR ; blokje was onzichtbaar - ; wordt nu zichtbaar - POP BC - POP HL - DJNZ DOCLEARLOOP - RET - ZICHTBAAR: LD A,(FOUND) - INC A - LD (FOUND),A - JP MAAKZICHTBAAR - NEGATIEF: DEC B ; 255 - RET - - Om bij HL een 8 bits getal op te tellen moet je dit 8 bits - getal in BC zetten (DE kan ook). B moet 0 gemaakt worden en in - C moet het 8 bits getal gezet worden. - - Door GEN80 wordt -1 vertaald in 256-1=255 - -16 wordt dus 256-16=240 - - Bij 8 bits getallen was het zo dat optellen met 255 hetzelfde - betekende als er 1 van aftrekken, maar bij 16 bits getallen - wordt er gewoon 255 bij opgeteld. - Als B echter op 255 staat werkt de truuk wel weer. - Hiervoor zorgt de subroutine NEGATIEF. - - Zoals je kunt zien maak ik weer gebruik van de routine - MAAKZICHTBAAR, die ik voor de overzichtelijkheid hieronder - nog maar even herhaal: - - MAAKZICHTBAAR: - SET 6,(HL) ; in DATA aangeven dat - ; dit blokje al - LD HL,AANTALZICHTBAAR; zichtbaar is - INC (HL) - RET - - Merk verder nog op dat HL telkens bewaard moet worden ( op de STACK ), omdat - uitgegaan wordt van Offset's t.o.v. het adres van het lege blokje. - - Verder wil ik nog even kwijt dat de routine CLEARDATA vast wel - op de een of andere manier sneller kan gemaakt worden.(b.v. - door gebruik van de overgebleven bit in de DATA, om aan te - geven of een leeg blokje als eens onderzocht is) - Maar persoonlijk vond ik dat niet nodig, aangezien ik het dan - alleen maar moeilijker zou maken dan het eigenlijk is. - - - Zo, tot zover de bespreking van de routines van het spel - Minesweeper. - - De listing staat in zijn geheel nog een keer op de Future- - Disk als ASCII-tekst in MINESW.GEN. - Wil je de routine in WBASS2 gebruiken, moet je wel eerst de - header weghalen. Dus deze routine moet eruit: - - DB #FE ; om de file in BASIC - DW ST ; m.b.v. BLOAD in te kunnen laden - DW EN ; weglaten bij gebruik van WBASS2 - DW ST - - Ik wens je erg veel plezier met deze routines en daag je uit - de volgende uitbreidingen eens te programmeren: - - - Een routine, die zelf random velden opbouwt. - Op zich is dit niet zo moeilijk als je misschien denkt. - Als buffer voor randomgetallen gebruik je een geschikt - deel van het geheugen b.v. de basicrom, waarin je met - LD A,R een adres kiest. - Staat op een adres een b.v. waarde >196 zet je een mijn - neer, anders niet. M.b.v. de al geschreven routine voor - het random wissen moet je nu vrij eenvoudig een routine - kunnen schrijven die rondom de juiste getallen plaatst. - Aangezien deze routine wezenlijk is voor het spel zal ik - misschien op een van de volgende FutureDisks de routine - publiceren. - - fatsoenlijke routine, die aangeeft dat je gewonnen bent - i.p.v wat nutteloze Beeps, die alleen een programmeur - interessant vind (om te testen). - - Als je afgaat wordt het hele veld zichtbaar gemaakt, maar - alle vlaggen blijven staan zodat je niet kunt zien of - hieronder echt een mijn zat. - Los dit b.v. op door een routine te schrijven die alle 5e - bit's in het dataveld 0 maakt (de vlaggen weghaalt), voor- - dat VULSCHERM wordt aangeroepen. - - Hetzelfde spel omzetten naar Screen 7, een klokje toevoe- - gen, puntentelling bijhouden en de snelste tijd laten zien. - - Blokjes 8x8 formaat geven (en dus meer blokjes op het - scherm zetten). - - SUCCES !! - -Ruud Gelissen diff --git a/Future Disk/28/MSX-DOS2 deel 2.md b/Future Disk/28/MSX-DOS2 deel 2.md deleted file mode 100644 index b880473..0000000 --- a/Future Disk/28/MSX-DOS2 deel 2.md +++ /dev/null @@ -1,94 +0,0 @@ - De DOS2 cursus gaat weer verder... - - ASCII'S WAY TO TORMENT MANKIND - - ���� - ���� - ���� - ���� - - - - Oftewel, het is weer tijd voor DOS2. Niet zoveel deze keer, - want echt veel tijd heb ik niet. Voor deze keer maar een paar - functies specifiek onder de loep, we komen vanzelf een keer - aan bij $70. Overigens ga ik inderdaad niet de DOS1 calls - behandelen. Deze info heeft wel vaker ergens anders gestaan. - Mocht er nu echt iemand zijn die daar toch intresse in heeft, - dan is een belletje naar de redactie genoeg om dat probleem - op te lossen. - - - GET DISK PARAMETERS [_DPARM] - - IN: C = $31 - DE = Pointer to 32byte buffer - L = Drive number - RES: A = Error code - DE = Preserved - - Created block: +$00 Physical drive number - +$01 Sector size ($01FF) - +$03 Sector per cluster - +$04 Number of reserved sectors - +$06 Number of FATs - +$07 Entries in root directory - +$09 Number of logical sectors - +$0B Media descriptor byte - +$0C Sectors per FAT - +$0D First root directory sector - +$0F First data sector - +$11 Maximum cluster number - +$13 Dirty disk flag - +$14 Volume ID - +$18 1F Unused - - - - FIND FIRST ENTRY [_FFIRST] - - IN: C = $40 - DE = File info block / ASCIIZ string pointer - HL = ASCIIZ filename pointer (If DE = FIB) - B = Attributes - IX = New file info block - RES: A = Error code - IX = Matching entry - - - - FIND NEXT ENTRY [_FNEXT] - - IN: C = $41 - IX = Pointer to file info block from _FFIRST - RES: A = Error code - IX = Matching next entry - - - FIND NEW ENTRY [_FNEW] - - IN: C = $42 - DE = File info block / ASCIIZ string pointer - HL = ASCIIZ filename pointer (If DE = FIB) - B = Attributes - IX = New file info block - RES: A = Error code - IX = New entry - - - - OPEN FILE HANDLE [_OPEN] - - IN: C = $43 - DE = Drive/path/file ASCIIZ of FIB - A = Mode: b0, no write b1, no read b2 inheritable - RES: A = Error code - B = New file handle - - - En dat was 't alweer. Sorry, ik weet 't, het is niet veel, - maar om eerlijk te zijn heb ik ook wel wat beters te doen. - Zoals slapen, want het is al weer gruwelijk laat... Tot FD 29 - maar weer, met hopelijk iets meer dan deze aflevering... - -Tobias Keizer diff --git a/Future Disk/28/MSX-DOS2 deel 3.md b/Future Disk/28/MSX-DOS2 deel 3.md deleted file mode 100644 index 7745a8d..0000000 --- a/Future Disk/28/MSX-DOS2 deel 3.md +++ /dev/null @@ -1,96 +0,0 @@ - THE DOS2 COURSE GOES ON AND ON AND... - ASCII'S WAY TO TORMENT MANKIND - - ���� - ���� - ���� - ���� - - - - In other words, it time for DOS2 again. Not too much this time - as time is indeed something I do not have... Just a few func- - tions a little more specified, we'll reach $70 eventually, - some day... Right?!? Ah well, we'll see... By the way, I'm - not going to go into all that DOS1 BDOS crap, just the speci- - fic DOS2 calls... DOS1 info can be found practically every- - where, but if someone really wants that info, a call -as in - phonecall, letter - will suffice to solve that problem. - - - - GET DISK PARAMETERS [_DPARM] - - IN: C = $31 - DE = Pointer to 32byte buffer - L = Drive number - RES: A = Error code - DE = Preserved - - Created block: +$00 Physical drive number - +$01 Sector size ($01FF) - +$03 Sector per cluster - +$04 Number of reserved sectors - +$06 Number of FATs - +$07 Entries in root directory - +$09 Number of logical sectors - +$0B Media descriptor byte - +$0C Sectors per FAT - +$0D First root directory sector - +$0F First data sector - +$11 Maximum cluster number - +$13 Dirty disk flag - +$14 Volume ID - +$18 1F Unused - - - - FIND FIRST ENTRY [_FFIRST] - - IN: C = $40 - DE = File info block / ASCIIZ string pointer - HL = ASCIIZ filename pointer (If DE = FIB) - B = Attributes - IX = New file info block - RES: A = Error code - IX = Matching entry - - - - FIND NEXT ENTRY [_FNEXT] - - IN: C = $41 - IX = Pointer to file info block from _FFIRST - RES: A = Error code - IX = Matching next entry - - - - FIND NEW ENTRY [_FNEW] - - IN: C = $42 - DE = File info block / ASCIIZ string pointer - HL = ASCIIZ filename pointer (If DE = FIB) - B = Attributes - IX = New file info block - RES: A = Error code - IX = New entry - - - - OPEN FILE HANDLE [_OPEN] - - IN: C = $43 - DE = Drive/path/file ASCIIZ of FIB - A = Mode: b0, no write b1, no read b2 inheritable - RES: A = Error code - B = New file handle - - - - And that's all folks. Sorry, I know, it aint much, but to be - hounest even I have got better things to like. Like sleeping, - for instance, because it's really terribly late... Till FD#29 - I guess, with -hopefully- a little more than this time... - -Tobias Keizer diff --git a/Future Disk/28/The PCM sample processor.md b/Future Disk/28/The PCM sample processor.md deleted file mode 100644 index df45d97..0000000 --- a/Future Disk/28/The PCM sample processor.md +++ /dev/null @@ -1,102 +0,0 @@ - Bla bla bla bla - The PCM sample processor, the truth... - - ���� - ���� - ���� - ���� - - - - - Those good old days... I can remember them like it was - yesterday... Remember those stories in all the magazines when - the Turbo-R (ST) was released in Japan? A 28.8Mhz CPU, loads - of built-in software and a PCM-Samplechip. WOW!! Now it would - be possible to use samples with your music, or voice-recogni - sion. Yeah, righty... But still, the PCM isn't at all bad... - - -Music - - Were the music part is concerned, there aren't that many - options, unfortunately. Adressing the PCM chip takes too much - time for any other things to be done. Music + samples there- - fore isn't really an option. It is possible, but the sample - freuency has to be very low (No more than 12Khz) and there - will be a 60Hz rustle on the back of the sound. For something - like a drum, that's not too big a problem. But when it comes - to speach or something like that, you'll notice. - - The FD#25 game Ryu No Chie is a nice example of what I mean. - The sample frequency there was 8Khz, the music was played via - a slightly modified Moonblaster replayer in stereo mode. - Naturally, that wasn't the best a Turbo-R can do. For one, - the R800 wasn't on, and the R800 mode is at least 4 times - faster than the Z80 mode. Furthermore, the standard interrupts - where activated, which isn't too clever either. - -FREQUENCY - - The previously mentioned magazines told us the maximum sample - frequency on a Turbo-R was about 16KHz. Not at all true... In - ideal circumstances a sample (play!) frequency of 400KHz(!!!) - should not be a problem. But, like said, under ideal circum- - stances...Think OTIR in cases like these. However, under not - so ideal circumstances (read, a full-function PCM player) 16 - Khz is not the top by far. A sample frequency of 44KHz (CD - quality) should not give any problems either. However, the - big problem is recording those samples. As the samples are - recorded with only one bit, is takes a lot more CPU time to - record a sample, than it does to play one... Too bad... - - I haven't calculated all this, but I think recording should be - possible at a sample-rate of 24Khz, playing has very fiew - limits... - - -HOW TO PLAY A SAMPLE... - - Let's make a little program that plays a sample from $4000 - till $BFFF. Let's assume we do not need any interrupts, and - it is not possible to abort the process. Here's what you'd - get: - - BEGINN: LD HL,$4000 - LD BC,$8000 - LD A,%00000010 - OUT ($A5),A - - MAINLP: LD A,(HL) - OUT ($A4),A - INC HL - DEC BC - LD A,B - OR C - RET Z - JP MAINLP - - A small player like this one would put you well over the 44Khz - C quality. And when I say well over, I mean well over. If I - take a short look a this, it would put the sample rate at pro- - bably trice the frequence of that of a CD player... But, I - could be wrong... (I'm probably not though) Only remaining - problem is it won't be possible to record samples on a Turbo-R - at that frequence, you'll need quite a PC for that. Other pro- - blem is that at a frequence this high, 32kB's of sample isn't - really a lot to listen to. But still, that 16KHz really wasn't - all that accurate... - - Anyway, I suggest that those interested juggle a little with - this small source, and we'll continue next time, with a real - player with adjustable sample-frequency! How nice... - - By the way, that first OUT is to set the PCM chip for: - - Play sample, Don't send MIC in to speaker, Don't disable - Sound chips (Music/PSG), activate filter... - - Well, good luck... - And till next time... - -Tobias Keizer diff --git a/Future Disk/30/Advanced Basic.md b/Future Disk/30/Advanced Basic.md deleted file mode 100644 index 7199393..0000000 --- a/Future Disk/30/Advanced Basic.md +++ /dev/null @@ -1,90 +0,0 @@ - Daar gaan we dan weer: alweer zo'n programmeer-tekst...ditmaal Advanced Basic... - - - CURSUS ADVANCED BASIC - - - - Voor diegenen die niet genoeg hebben aan een handleiding en - wat meer voorbeelden willen, is hier een kleine cursus, die - ongeveer 3 a 4 delen zal beslaan. - - - I WANT TO USE WINDOWS - - Het belangrijkste gedeelte zijn natuurlijk de windows. In - Advanced BASIC zijn windows ALLEEN te gebruiken is scherm 0, - de schermbreedte moet minstens 41 zijn. Er kunnen maximaal - 16 windows tegelijk gebruikt worden, maar afhankelijk van de - grootte kunnen dat er minder worden. De maximale grootte van - een window is 80 bij 24, in dat geval worden de functietoet- - sen ook overschreven. De inhoud van zo'n window is 78 bij 22 - tekens. De minimale grootte van een window is 3 bij 3, de - inhoud is dan 1 bij 1. Als een window te groot is voor het - scherm, dan wordt dat (natuurlijk) gemeld. - - Een window is te maken met _WINDOW(X,Y,BREEDTE,HOOGTE). X en - Y geven de positie van de linkerbovenhoek aan en BREEDTE en - HOOGTE geven aan wat de naam al zegt. Een voorbeeld: - - 10 REM Mijn eerste window - 20 KEY OFF:_WINDOW(0,0,80,24) - 30 A$=INPUT$(1) - RUN - - Er verschijnt een window op locatie 0,0 die 80 bij 24 groot - is. - - WE WANT TEXT - - Met _PRINT(STR$) is het mogelijk om een string in de laatst - gemaakte window te printen. Als het einde van het window - bereikt is, scrollt de inhoud omhoog, tenzij een _SCROLLOFF - geven is. _SCROLLON doet het omgekeerde van _SCROLLOFF en - zorgt dus dat de inhoud wel kan scrollen. - - Maar goed, ik dwaal af. Eh, _PRINT dus. Het is niet mogelijk - om een getal op het scherm te zetten. Nou ja, niet direct. - Het is natuurlijk wel mogelijk om een getal om te zetten - naar een string. Een voorbeeld: - - 10 REM Mijn tweede window - 20 CLS:_WINDOW(0,0,80,3) - 30 _PRINT("Dit is mijn tweede window! Joepie!") - 40 LOCATE 0,3 - 50 A$=INPUT$(1) - RUN - - Er verschijnt een leuk windowtje met daarin de tekst zoals - aangegeven in regel 30. - - THATS NOT ALL - - De plek waar de tekst geprint moet worden in een window, kan - bepaald worden met _LOCATE(X,Y) en werkt hetzelfde als - LOCATE in gewoon BASIC. Als de plek buiten het scherm is, - komt er een foutmelding. Een klein voorbeeldje: _LOCATE(0,0) - zet de cursor in de linkerbovenhoek (hetgeen ook kan met - _HOME). - - Met _WCLS wordt de inhoud van de laatst gemaakte window - gewist. _RWIN haalt een window weg en herstelt datgene dat - achter het window zat. Het is ook mogelijk om alle windows - te wissen, dat kan met _RALLWIN. Ook hier wordt de - achtergrond weer hersteld. - - I LIKE SCROLLIN' AND MOVIN' - - Omdat mensen houden van scrollende dingen, zit er in - Advanced BASIC ook een optie daarvoor, nee, eigenlijk wel - vier, namelijk: _UP, _DOWN, _LEFT en _RIGHT. - - Deze commando's scrollen de inhoud van de laatst gemaakte - window in de aangegeven richting. - - WE WANT MORE - - Helaas, helaas, volgende keer meer! - - -Arjan Bakker diff --git a/Future Disk/30/Assembly voor beginners.md b/Future Disk/30/Assembly voor beginners.md deleted file mode 100644 index 22edbb2..0000000 --- a/Future Disk/30/Assembly voor beginners.md +++ /dev/null @@ -1,106 +0,0 @@ - De beginnertjes hebben het goed dit keer!!! Een gehele assymbly cursus voor jullie... - - - ASSEMBLY VOOR BEGINNERS - - - In deze rubriek komen routine's aan bod die nuttig zijn en - vaak gebruikt worden. Degenen die geen assembly kunnen, - hebben niets aan deze cursus. In dit eerste deel komt de - vermenigvuldigings-routine aan bod. - - - HOE DOEN WE DIT DAN? - - Okay, eerst eventjes laten zien hoe het dus niet moet, zoals - beginners het vaak doen (schaam je niet, ik deed het eerst - ook zo). Vermenigvuldigen gebeurt meestal botweg als - herhaald optellen van een getal. Bijvoorbeeld, 15 * 25 is - het resultaat van 25 + 25 + ... + 25 + 25 (in totaal 15 keer - het getal 25 en 14 keer het plusteken). Als source ziet dit - er zo uit: - - LD BC,15 - LD DE,25 - LD HL,0 - - MULUW: ADD HL,DE - DEC BC - LD A,B - OR C - JP NZ,MULUW - RET - - Natuurlijk, bij kleine getallen werkt dit wel snel, maar als - je grote getallen gebruikt, is een andere methode veel - sneller. - - - TERUG NAAR DE BASISSCHOOL - - Hoe pakken we het dan wel aan? Nou, ik zal even een voor- - beeldje geven hoe ik het geleerd heb op de basisschool. - - 15 - 25 - --- x - 5 * 15 = 75 - 2 * 150 = 300 - --- + - 375 - - Telkens als we een getal naar links gaan, dan vermenigvul- - digen we het eerste getal met 10. Op de MSX gaat het net zo, - maar nu moeten we even binair denken, dus vermenigvuldigen - we met 2, in plaats van 10. Hetzelfde voorbeeldje nog eens, - maar nu in het binaire talstelsel. - - 1111 = 15 - 11001 = 25 - -------- x --- x - 1 * 1111 = 1111 = 15 - 0 * 11110 = 0 - 0 * 111100 = 0 - 1 * 1111000 = 1111000 = 120 - 1 * 11110000 = 11110000 = 240 - -------- + ----- + - 101110111 = 375 - - Zoals je ziet, klopt dit als een bus. - - - NU OP DE MSX - - We gaan er even van uit dat de te vermenigvuldigen getallen - in BC en DE staan en dat het resultaat in HL komt. De source - ziet er dan als volgt uit: - - LD DE,25 ;De te vermenigvuldigen getallen. - LD BC,15 - - MULUW: LD HL,0 ;HL moet 0 zijn bij het begin - - MULUW1: SRL D ;Deel DE door 2. Als DE oneven was, - RR E ;wordt, de carry-flag gezet. - - JR NC,MULUW2 ;Carry-flag niet gezet? Niet optellen. - ADD HL,BC ;BC optellen bij resultaat. - - MULUW2: LD A,D ;Als DE 0 is, zijn we klaar. - OR E - RET Z - - SLA C ;Vermenigvuldig BC met 2. - RL B - JP MULUW1 ;Terug naar MULUW1 - - Met een CALL naar MULUW kun je de getallen in DE en BC snel - met elkaar vermenigvuldigen, het resultaat komt in HL. - - Als het goed is, is het nu duidelijk hoe het werkt. Zo niet, - lees de tekst dan nog maar eens over. - - Oja mensen, er staan .ASM files op deze FD. Dus dan kun je - het allemaal nog eens rustig bekijken (ASSEMBL1.ASM). - -Arjan Bakker diff --git a/Future Disk/30/Paint in ML.md b/Future Disk/30/Paint in ML.md deleted file mode 100644 index e46c28a..0000000 --- a/Future Disk/30/Paint in ML.md +++ /dev/null @@ -1,78 +0,0 @@ - Hoe kunnen we verven in ML???? Awel, na het lezen van deze tekst wordt het ons allemaal duidelijk... - - - PAINT IN ML - - - - Het is lastig om zelf een routine te maken die een vlak kan - inkleuren. Zo'n routine hoeft helemaal niet gemaakt te - worden, want in de SUB-ROM zit al zo'n routine. Deze is - echter niet zonder meer te gebruiken, want de routine is - voor de BASIC-interpreter. - - Om de routine te gebruiken, moet je een stukje BASIC - aanmaken in ML. In dit geval is dit niet lastig, tenminste, - als je de codes weet. - - - WAT IS ER NODIG - - De routine die voor het painten gebruikt wordt, heeft alleen - maar een klein stukje BASIC nodig, namelijk datgene dat - achter het commando PAINT komt. - - Dit stukje ziet er zo uit: - - db 40,28,0,0,44,28,0,0,41,44,28,0,0,44,28,0,0,0 - - De 40 geeft een haakje openen aan, 28 geeft aan dat de - volgende 2 bytes een integer vormen, 44 betekent komma, 41 - is haakje sluiten, de laatste nul betekent dat de regel is - afgelopen en daarmee zijn alle codes uitgelegd. De bytes - betekenen dus: - - (integer,integer),integer,integer einde regel - - Bij het commando PAINT zien we dus dat het betekent: - - (x,y),vulkleur,randkleur einde regel - - Het enige wat je nu moet doen is de nullen vullen met een - waarde en routine #0069 in het SUBROM aanroepen. De volgende - listing doet dat. - - - DE SOURCE - - ; Kleur een vlak in (alleen scherm 5,6,7 en 8) - ; Werkt misschien ook op scherm 10, 11 en 12 - ; In: DE = X-coordinaat - ; HL = Y-coordinaat - ; B = vulkleur - ; C = randkleur - ; Verandert: AF, BC, DE en HL - - paint: ld (dat1+2),de - ld (dat1+6),hl - ld a,b - ld (dat1+11),a - ld a,c - ld (dat1+15),a - ld hl,dat1 - ld ix,#0069 - call #015f - ret - - dat1: db 40,28,50,0,44,28,50,0,41,44,28,15,0,44,28,15,0,0 - ; PAINT ( X , Y ) , VK , RK - - - Zoals je ziet is het erg eenvoudig. Voor de luitjes die te - lui zijn om deze source even over te tikken, staat de source - (als het goed is)(NvdR: en alles is goed!!!) ook op de disk - onder de naam PAINT.ASM. - - -Arjan Bakker - diff --git a/Future Disk/31/Advanced Basic 2.md b/Future Disk/31/Advanced Basic 2.md deleted file mode 100644 index d58caa7..0000000 --- a/Future Disk/31/Advanced Basic 2.md +++ /dev/null @@ -1,221 +0,0 @@ -Arjan vervolgt zijn cursus Advanced Basic... - -Cursus Advanced BASIC (2) - - Voordat ik weer wat commando's ga uitleggen, geef ik eerst - de bestelinformatie van Advanced BASIC 1.01. Smael was zo - dom dat hij vergat dat bij de recensie op FD #30 te zetten. - Maar goed, hier komt de informatie: - - Maak f 17,50 over op bankrekeningnummer 32.56.20.806 t.n.v. - Arjan Bakker te Hasselt o.v.v. AdvBASIC en je eigen naam en - adres. De bank is de Rabobank te Hasselt (Ov). - - -MORE ABOUT WINDOWS - - Nog niet alle windows-commando's waren behandeld de vorige - keer, dus komt hier de rest. - - Met _CSRLIN(adres) kun je de regel waar de cursor in een - window op staat opvragen. De regel komt dan in het opgegeven - adres terecht. - - Met _POS(adres) komt de x-positie van de cursor in een - window op het opgegeven adres terecht. - - _NWINDOW(adres) geeft het aantal gebruikte windows terug. - - _WINDATA(adres) geeft informatie over het window terug. Op - adres+0 staat de x-positie van het window, adres+1 is de - y-positie van het window, adres+2 de breedte en adres+3 de - hoogte. - - Een voorbeeld: - - 10 SCREEN 0 - 20 _WINDOW(0,0,80,5) - 30 _LOCATE(40,3) - 40 _CSRLIN(&HD000) - 50 _POS(&HD001) - 60 _NWINDOW(&HD002) - 70 _WINDATA(&HD003) - - Vanaf adres &HD000 komen de diverse data in het geheugen. - - -TRUUKJE - - Je kunt opgevraagde waardes ook direct in een variabele - stoppen. Dit gaat als volgt: - - _NWINDOW(VARPTR(N)) - - Het aantal aanwezige windows staat nu in variabele N. Let er - wel op dat de variabele N bestaat �n integer is, want anders - werkt het niet. Oh ja, deze truuk werkt niet bij _WINDATA. - - -MEER KLEUREN OP SCHERM 0 - - Screen 0 kan 4 kleuren tegelijk laten zien. Advanced BASIC - heeft hiervoor een viertal routines die dat wel erg - makkelijk voor jullie maken, namelijk: - - _COLOR(vg,ag,p1,p2). Vg is de voorgrondkleur, ag is de - achtergrondkleur, p1 is de periode dat de voorgrondkleur - zichtbaar is (in 1/50-seconden) en p2 is de periode dat de - achtergrondkleur zichtbaar is. - - Met _PUT(x,y,a) kun je een aantal karakters met andere - kleuren op het scherm zetten. X en y geven de x- en - y-positie weer en a is het aantal karakters. - - _UNPUT(x,y,a) doet het omgekeerde van _PUT, namelijk het - weghalen van de karakters. - - _CLS wist de alternatieve schermkleuren. - - Een voorbeeld: - - 10 SCREEN 0 - 20 _COLOR(15,0,15,15) - 30 _PUT(0,0,80*24) - 40 _UNPUT(0,0,80*24) - 50 GOTO 30 - - Het hele scherm wordt eerst gevuld met de alternatieve - schermkleuren en daarna worden deze weer gewist. Dan wordt - het scherm weer gevuld, gewist enz. enz. - - -TOT SLOT - - Tot slot komen hier nog wat simpele commando's. - - _CLBUF : Wist de toetsenbordbuffer. - _SNDOFF : Zet het PSG-geluid uit. - _CAPSON : Zet CAPS-lock aan. - _CAPSOFF : Zet CAPS-lock uit. - _INFO : Geeft wat informatie over Advanced BASIC. - _VERSION : Geeft het versie-nummer van Advanced BASIC. - - -DE VOLGENDE KEER - - De volgende keer komen de nieuwe disk-commando's aan bod. - Maar tot FD 32, dus maar! - - -Arjan Bakker -Arjan vervolgt zijn cursus Advanced Basic... - -Cursus Advanced BASIC (2) - - Voordat ik weer wat commando's ga uitleggen, geef ik eerst - de bestelinformatie van Advanced BASIC 1.01. Smael was zo - dom dat hij vergat dat bij de recensie op FD #30 te zetten. - Maar goed, hier komt de informatie: - - Maak f 17,50 over op bankrekeningnummer 32.56.20.806 t.n.v. - Arjan Bakker te Hasselt o.v.v. AdvBASIC en je eigen naam en - adres. De bank is de Rabobank te Hasselt (Ov). - - -MORE ABOUT WINDOWS - - Nog niet alle windows-commando's waren behandeld de vorige - keer, dus komt hier de rest. - - Met _CSRLIN(adres) kun je de regel waar de cursor in een - window op staat opvragen. De regel komt dan in het opgegeven - adres terecht. - - Met _POS(adres) komt de x-positie van de cursor in een - window op het opgegeven adres terecht. - - _NWINDOW(adres) geeft het aantal gebruikte windows terug. - - _WINDATA(adres) geeft informatie over het window terug. Op - adres+0 staat de x-positie van het window, adres+1 is de - y-positie van het window, adres+2 de breedte en adres+3 de - hoogte. - - Een voorbeeld: - - 10 SCREEN 0 - 20 _WINDOW(0,0,80,5) - 30 _LOCATE(40,3) - 40 _CSRLIN(&HD000) - 50 _POS(&HD001) - 60 _NWINDOW(&HD002) - 70 _WINDATA(&HD003) - - Vanaf adres &HD000 komen de diverse data in het geheugen. - - -TRUUKJE - - Je kunt opgevraagde waardes ook direct in een variabele - stoppen. Dit gaat als volgt: - - _NWINDOW(VARPTR(N)) - - Het aantal aanwezige windows staat nu in variabele N. Let er - wel op dat de variabele N bestaat �n integer is, want anders - werkt het niet. Oh ja, deze truuk werkt niet bij _WINDATA. - - -MEER KLEUREN OP SCHERM 0 - - Screen 0 kan 4 kleuren tegelijk laten zien. Advanced BASIC - heeft hiervoor een viertal routines die dat wel erg - makkelijk voor jullie maken, namelijk: - - _COLOR(vg,ag,p1,p2). Vg is de voorgrondkleur, ag is de - achtergrondkleur, p1 is de periode dat de voorgrondkleur - zichtbaar is (in 1/50-seconden) en p2 is de periode dat de - achtergrondkleur zichtbaar is. - - Met _PUT(x,y,a) kun je een aantal karakters met andere - kleuren op het scherm zetten. X en y geven de x- en - y-positie weer en a is het aantal karakters. - - _UNPUT(x,y,a) doet het omgekeerde van _PUT, namelijk het - weghalen van de karakters. - - _CLS wist de alternatieve schermkleuren. - - Een voorbeeld: - - 10 SCREEN 0 - 20 _COLOR(15,0,15,15) - 30 _PUT(0,0,80*24) - 40 _UNPUT(0,0,80*24) - 50 GOTO 30 - - Het hele scherm wordt eerst gevuld met de alternatieve - schermkleuren en daarna worden deze weer gewist. Dan wordt - het scherm weer gevuld, gewist enz. enz. - - -TOT SLOT - - Tot slot komen hier nog wat simpele commando's. - - _CLBUF : Wist de toetsenbordbuffer. - _SNDOFF : Zet het PSG-geluid uit. - _CAPSON : Zet CAPS-lock aan. - _CAPSOFF : Zet CAPS-lock uit. - _INFO : Geeft wat informatie over Advanced BASIC. - _VERSION : Geeft het versie-nummer van Advanced BASIC. - - -DE VOLGENDE KEER - - De volgende keer komen de nieuwe disk-commando's aan bod. - Maar tot FD 32, dus maar! - - -Arjan Bakker - diff --git a/Future Disk/31/Disk IO in BASIC.md b/Future Disk/31/Disk IO in BASIC.md deleted file mode 100644 index 2730f36..0000000 --- a/Future Disk/31/Disk IO in BASIC.md +++ /dev/null @@ -1,236 +0,0 @@ - Tobias leert ons wat meer over Disk I/O in BASIC... -BASIC, de drive laten ratelen... - - ���� - ���� - ���� - ���� - - - Dat de MSX BASIC een van de beste -zo niet de beste- BASIC - varianten is mag bekend zijn. Geen BASIC soort is zo goed uit- - gerust als MSX BASIC. Werkelijk alles is mogelijk. Ik geloof - dat de line-interrupt zo'n beetje het enige is dat BASIC niet - ondersteunt. Maar ook daar is indirect een oplossing voor. - Want MSX BASIC laat zich ideaal met machinetaal combineren. En - een drivertje is zo geschreven. - - Van muziek tot zelfs scroll routines, allemaal op de interrupt - erbij. Dat het er allemaal niet sneller op wordt mag duidelijk - zijn, maar het kan. Maar ook zonder die ML is er in MSX BASIC - een hele hoop mogelijk. - - - Disk I/O - - - Zo is ook het DISK I/O gedeelte van MSX BASIC niet misselijk, - van binaire files tot random-access file. Het kan allemaal. Om - precies te zijn heeft de DISK BASIC maar twee nadelen. Het eer - ste grote nadeel is dat er in BASIC geen data files zijn in te - laden. Elke file moet een HEADER hebben; BLOAD files dus. Dit - is een probleem waar ik in een latere aflevering nog wel eens - op terug kom. Een ander probleem is dat het in BASIC niet fat- - soenlijk mogelijk is om een directory op het scherm te zetten. - Dat kan eigenlijk alleen maar met het FILES commando. Het eer- - ste probleem is dan dus al dat de directory informatie op een - scherm moet kunnen passen. En onder DOS2 hoeft dat zeer zeker - niet het geval te zijn. Het tweede probleem is dat we vast zit- - ten aan de "layout" die BASIC ons voorschrijft. En manipulatie - van de directory is er al helemaal niet bij. - - Een veel gebruikte oplossing is om het scherm "uit" te zetten, - vervolgen het FILES commando te gebruiken, met een paar wel- - gemikte VPEEKs de data in variabelen te zetten om vervolgens - het oude scherm weer op te bouwen en de nieuwe data te printen - op het scherm. Aan een dergelijke kunstgreep kleven een aantal - nadelen. Ten eerste is het natuurlijk een weinig elegante, en - zeker niet makkelijke, oplossing. En ten tweede is zulks erg - lastig in een grafisch scherm. Er moet namelijk eerst naar het - tekst-scherm worden gegaan, waardoor bij terug keer naar het - grafische scherm heel page 0 gewist is. Allemaal niet erg han- - dig dus. Terwijl er een prima oplossing is...maar ja, onbekend - maakt onbemind... - - - DSKI$ & DSKO$ - - Met deze twee BASIC functies is het mogelijk om sectoren resp. - in te lezen en weg te schrijven. Bij de tweede functie volsta - ik met de syntaxis aangezien het schrijven van sectoren bij - het lezen van directories weinig waarde heeft. De syntaxis: - - A$ = DSKI$ (d,s) ; Voor het lezen van sector s van drive d - DSKO$ d,s ; Voor het schrijven van sector s op drive d - - Merk hier het verschil op tussen de syntaxis van beide instruc- - ties. De vorm van het DSKI$ commando doet vermoeden dat de - sector in de variabele A$ wordt gelezen of iets dergelijks. - Niets is echter minder waar. De sector wordt namelijk ingelezen - in een vaste buffer. En daar laten vrijwel alle BASIC boeken - het afweten. Geen van de boeken vermeld namelijk waar die - buffer dan wel in het geheugen te vinden is. - - De buffer staat overigens niet op een vaste plaats. De pointer - naar deze buffer uiteraard wel. En wel op adres $F351. Door - dus het adres van $F351 / $F352 af te plukken wordt dus het - adres van de sector buffer gevonden. Minder bekend is echter - dat dit adres ook weg te poken is. En daar komt de truuk. Want - we kunnen in plaats van het adres weg te poken veel beter zelf - ons adres bepalen. Dan zijn er immers veel minder adres-varia- - belen in ons programma nodig wat de snelheid nog wel eens ge- - voelig ten goede kan komen. - - POKE &HF351,&H00 : POKE &HF352,&HC0 - - Dit zal dus de meest logische oplossing zijn. Het adres $C000 is - namelijk een prima test adresje voor allerlei zaken. Voordeel - van de POKE methode is ook dat er ook andere machinetaal pro- - gramma's gebruikt kunnen worden zonder dat alles vast komt te - liggen. Gebruiken we bijvoorbeeld de MoonBlaster 1.4 BASIC - driver dan wordt er op adres $DA00 het een en ander aan gege- - vens neergezet. Doordat we precies weten waar onze data te- - recht komt hoeft er dus nooit iets mis te gaan. Want of Moon- - Blaster erg vrolijk wordt van een FAT in de STEPBF buffer weet - ik niet... - - - Directory structuur - - Deze keer denk ik dat het wijsheid is om eerst alleen de DOS 1 - directory structuur te bespreken. De DOS 2 structuur is name- - lijk flink wat moeilijker. Het eerste voordeel is dat de direc- - tory altijd op een vaste plaats te vinden is. Namelijk sector - 07-14 op een dubbelzijdige disk, de enkelzijdige disk laat ik - maar even voor wat het is, maar met de hierna volgende formule - is ook dat prima uit te rekenen. - - First DIR Sector = Number Of FATS * Sectors Per FAT + 1 - - Maar, hoe komen we dan aan die informatie? Simpel, uit de BOOT - sector. De BOOT sector (sector 0) is een sector waaruit geBOOT - kan worden, en waar informatie over de disk staat. Zo ook de - informatie die we voor onze formule nodig hebben. Om een duide- - lijker beeld te scheppen is het misschien verstandiger om maar - eerst eens een liniear beeld van een disk te scheppen. - - -Lees verder in deel 2... - - Tobias leert ons wat meer over Disk I/O in BASIC... -BASIC, de drive laten ratelen... - Deel 2 - ���� - ���� - ���� - ���� - - - Om een duidelijker beeld te scheppen is het misschien verstan- - diger om maar eerst eens een liniear beeld van een disk te - scheppen. - - BOOT Sector (00) - FAT Sectoren - Directory Sectoren - Data-Area Sectoren - - Om dus de eerste directory sector te berekenen moeten we weten - hoeveel FAT sectoren er zijn, en daar moet dan 1 bijop geteld - worden voor de BOOT sector. Nu blijkt dat een disk meer dan - ��n FAT kan hebben. Sterker nog, voor zover ik weet hebben - alle disks voor de zekerheid minimaal 2 kopien van de FAT. - Maar dat aantal hoeft niet vast te zijn. Zo is het geen pro- - bleem om 5 of 6 FAT kopi�n te hebben, hoewel dat niet gebruike- - lijk is. Ook is de lengte van een FAT niet vast. Op een dub- - belzijdige disk zal dat altijd 3 zijn, maar op een enkelzijdig - diskje meestal 2, terwijl een harddisk er weer veel meer heeft - dan 3. Dit alles staat dus in de bootsector. Ons eerste comman- - do zal dus - - A$ = DSKI$ (0,0) - - zijn, waarbij drive 0 voor de default diskdrive staat. Dan is - het belangrijk om te weten waar in de bootsector wat staat. - Het overzicht hieronder is niet helemaal correct, maar wel af- - doende. Zo zal het aantal bytes per sector op een MSX altijd - 512 zijn. Cluster informatie komt nu ook nog niet aan bod, dat - komt allemaal in een later deel wel. - - +16, 1 byte; Aantal FATs op disk - +17, 2 bytes; Aantal entries per directory - +21, 1 byte; Media Descriptor ($F8 = SS, $F9 = DS) - +22, 2 bytes; Aantal sectoren per FAT - - Als we dus de eerste directory sector willen weten is het on- - der staande stukje BASIC voldoende. - - 10 POKE&HF351,&H00: POKE&H352,&HC0: A$=DSKI$(0,0) - 20 NF=PEEK(&HC000+16): SF=PEEK(&HC000+22): FD=NF*SF - - Wederom eigenlijk niet correct. Zo kan een FAT in principe na- - melijk groter zijn dan 255 sectoren. Erg groot is die kans - echter niet; dat zou een behoorlijke harddisk moeten zijn. Nu - we dus de eerste directory sector weten kunnen we eindelijk be- - ginnen met uitlezen. Als we de structuur van een directory ken- - nen tenminste... - - +00, 11 bytes; Filenaam met extensie (geen .) - +11, 01 byte; Attribuut byte - +22, 02 bytes; Tijd "file-creation" - +24, 02 bytes; Datum "file-creation" - +26, 02 bytes; Eerste cluster - +28, 04 bytes; Lengte file (in bytes) - - Op dit moment is alleen het eerste nog maar belangrijk, de - filenaam. Nu staat er in een directory sector echt niet ��n - filenaam, sterker nog er staan er zelfs 16. Wederom maar weer - een klein stukje BASIC, dat spreekt immers boekdelen... - - 10 POKE&HF351,&H00: POKE&H352,&HC0: A$=DSKI$(0,0) - 20 NF=PEEK(&HC000+16): SF=PEEK(&HC000+22): FD=NF*SF - 30 ME=PEEK(&HC000+17): DS=FD: LS=FD+(ME/32): DIMF$(ME) - 40 ' Read Loop - 50 IFDS>LSTHENEND: ELSEA$=DSKI$(0,DS) - 60 FORLP=0TO15: AO=LP*32:F$(DE)="" - 70 FORL=0TO10: F$(DE)=F$(DE)+CHR$(PEEK(&HC000+AO+L): NEXTL - 80 DE=DE+1: NEXTLP: DS=DS+1: GOTO50 - - Dit stukje BASIC werkt in principe prima, maar heeft twee vrij - grote nadelen. Zo worden gewiste bestanden en lege directory - entries ook in de arrays geplaatst. En dat kost flink was ge- - heugen, en zal bijna nooit de bedoeling zijn. - - - $00 / $E5 - - Twee getallen die we in de filenaam kunnen tegenkomen, die een - speciale betekenis hebben. Zo betekent de eerste dat het einde - van de directory is bereikt, en de tweede dat het bestand ge- - wist is. Ook hier zullen we dus op moeten checken. Ons BASIC - programmaatje zal dus iets anders moeten worden. - - 10 POKE&HF351,&H00: POKE&H352,&HC0: A$=DSKI$(0,0) - 20 NF=PEEK(&HC000+16): SF=PEEK(&HC000+22): FD=NF*SF - 30 ME=PEEK(&HC000+17): DS=FD: LS=FD+(ME/32): DIMF$(ME) - 40 ' Read Loop - 50 IFDS>LSTHENEND: ELSEA$=DSKI$(0,DS) - 60 FORLP=0TO15: AO=LP*32: F$(DE)="" - 70 ' Do Check - 80 IFPEEK(&HC000+AO)=&HE5THENGOTO110 - 90 IFPEEK(&HC000+AO)=&H00THENEND - 100 FORL=0TO10: F$(DE)=F$(DE)+CHR$(PEEK(&HC000+AO+L): NEXTL - 110 DE=DE+1:NEXTLP:DS=DS+1:GOTO50 - - Dit is al iets beter. Uiteraard is dit dus een deelprogramma. - Een GOSUB naar dit stukje BASIC zou dus beter zijn. Maar, het - laat wel duidelijk zien hoe in BASIC een directory netjes, en - vlekkeloos kan worden uitgelezen. ON ERROR routines zijn name- - lijk geen probleem bij DSKI$ en DSKO$. - - De volgende keer gaan we eerst nog maar eens wat verder in op - de materie, om de keer daarna DOS 2 directories uit te lezen. - Met sub-directories nog wel!! Het is toch wat, die MSX BASIC! - - -Tobias Keizer diff --git a/Future Disk/32/Pascal cursus 1 EN.md b/Future Disk/32/Pascal cursus 1 EN.md deleted file mode 100644 index b5f36fd..0000000 --- a/Future Disk/32/Pascal cursus 1 EN.md +++ /dev/null @@ -1,103 +0,0 @@ -# Pascal (1) - -Koen asked me to write a course on PASCAL. And because I -think PASCAL is a well structured and nice language I -agreed. - - Before I begin the real work (the course), I will do a short - introduction. PASCAL (the language) is given the name of - Blaise Pascal the mathematician who lived from 1623 till - 1662. He was one of the great mathematicians that lived. He - laid down the basics for calculating changes. One of his - 'hobbies' was trying to create machines that did mathematics. - He created a machine that could do various calculations (not - only adding and subtracting) that was entirely mechanical - (try to imagine this). - - In about 1970 The name PASCAL (in capitals) was - 'reintroduced'. Professor Niklaus Wirth though it nice to - name his new programming language to the great mathematician. - I think most people have heard or read about PASCAL. PASCAL - has a lot of advantages compared to BASIC. PASCAL is almost - self documenting because of its structure. - - And now for the real thing. Lets begin with the structure of - a PASCAL program: - - PROGRAM program_name (INPUT,OUTPUT); - - CONST - {Constant definition} - - TYPE - {Type definition} - - VAR - {Variable declaration} - - {Procedure and function definition} - - BEGIN - {Main program} - END. - - All words in capitals are reserved words. This means that - this name cannot be used for something else (a variable for - instance), they have a special function in a program. PROGRAM - indicates that where about to make a PASCAL program. It is - followed by the name of the program and the words INPUT and - OUTPUT between brackets. The words INPUT and OUTPUT tell the - compiler that the program uses standard in- and output - (keyboard, screen). When working with files we will include - more between the brackets. - - After the program heading a block with constant, type and - variable declaration follows. PASCAL forces you to declare - all variables that you use in the program in advance. This - not as in BASIC where you can declare a variable when you - need it. - - After this the procedure and function declarations follow. - These declarations are equal to the 'program' declaration. - In a later course we will handle this. - - The last thing is a PASCAL program is the main program. The - main program is enclosed by BEGIN and END. - - That's it for the first course. I will leave you with a small - and simple PASCAL program. Try to compile and run it and see - if you can understand it. - -``` - PROGRAM simple (INPUT,OUTPUT); - - VAR - Value_1 : integer; - Value_2 : integer; - Result : integer; - - PROCEDURE input_value(VAR value:integer); - - BEGIN (* input_value *) - Write('Input a value : '); - Readln(value); - Writeln; - END; (* input_value *) - - BEGIN (* mainprogram *) - Writeln('Example program for PASCAL-course (1)'); - Writeln('FutureDisk'); - Writeln; - Writeln('Made by :'); - Writeln('Jeroen Smael'); - Writeln; - Writeln; - input_value(Value_1); - input_value(Value_2); - Result:=Value_1+Value_2; - Writeln(Value_1:1,' + ',Value_2:1,' = ',Result:1); - Writeln; - END. (* mainprogram *) -``` - - Jeroen 'PASCAL is fun' Smael \ No newline at end of file diff --git a/Future Disk/32/Pascal cursus 1 NL.md b/Future Disk/32/Pascal cursus 1 NL.md deleted file mode 100644 index bf523d5..0000000 --- a/Future Disk/32/Pascal cursus 1 NL.md +++ /dev/null @@ -1,156 +0,0 @@ -# Pascal (1) - - Men heeft mij gevraagd om een cursus PASCAL te schrijven. En - omdat ik PASCAL een goede, gestructureerde en leuke taal - vind, heb ik ja gezegd. - - Voordat ik ga beginnen met het echte werk, geef ik eerst een - korte inleiding over wat PASCAL precies inhoudt. PASCAL is - vernoemd naar de wiskundige Blaise Pascal die van 1623 tot - 1662 leefde. Blaise Pascal was ÇÇn van de grootste wiskundige - die de wereld gekend heeft. Hij heeft onder andere de - fundamenten gelegd van het kansrekenen. Maar het bekenste wat - Blaise Pascal heeft gedaan (buiten zijn bekende driehoek) is - het constru◊ren van een rekenmachine. Deze machine kon veel - rekenkundige berekeningen uitvoeren, en dat terwijl het - geheel alleen maar uit tandwielen en dergelijke bestond - (probeer je dat eens voor te stellen). - - Rond 1970 dook de naam PASCAL (geheel in hoofdletters) weer - op. Dit omdat ene Professor Niklaus Wirth het leuk vond om - zijn zojuist ontwikkelde programeertaal te vernoemen naar - Blaise Pascal. En deze taal is nu hÇÇl bekend. De meeste - mensen hebben er ervaring mee, of hebben er wel van gehoord. - Het voordeel van PASCAL boven BASIC is de gestructureerdheid. - Is het verplicht bij BASIC om commentaar te plaatsen (zeker - als iemand anders er iets van moet begrijpen) bij PASCAL wordt - de helft van de 'documentatie' door de gestructureerdheid van - de taal zelf verzorgd. Hiermee bedoel ik dat je er bij BASIC - een spagetti van kunt maken (met behulp van GOTO-instructies) - die niet te lezen is. Terwijl je bij PASCAL het programma - veel sneller doorziet door het inspringen (wordt later - duidelijk), de grotere verscheidenheid aan herhalingslussen - (WHILE, REPEAT en FOR) en het (bijna) niet voorkomen van - GOTO-instructies. - - Tot zover de inleiding. Nu gaan we dus echt beginnen. Dat - echt beginnen houdt in dat ik de globale structuur van een - PASCAL-programma ga uitleggen. - - De globale structuur van een PASCAL-programma is als volgt : - - PROGRAM programma_naam (INPUT,OUTPUT); - - CONST - {Constante definitie} - - TYPE - {Type definitie} - - VAR - {Variabelen declaratie} - - {Procedure en functie definitie} - - BEGIN - {Hoofdprogramma} - END. - - Alle woorden die hierboven met hoofdletters staan geschreven - zijn gereserveerde woorden. Dat wil zeggen dat deze naam niet - voor iets anders gebruikt kan worden en dat ze een speciale - functie hebben in een programma. Als we bovenaan beginnen dan - komen we als eerste het gereserveerde woord PROGRAM, gevolgd - door "programma_naam" tegen. Dit geeft voor de PASCAL- - compiler aan dat hier een programma met de naam - "programma_naam" begint. Verder volgen er de woorden INPUT en - OUTPUT (tussen haakjes). Deze woorden geven aan dat dit - programma gebruik maakt van de standaard in- en uitvoer - (toetsenbord en beeldscherm). Bij deze twee (gereserveerde) - woorden kunnen nog andere woorden staan, maar daar komen we - pas op als we het over file's gaan hebben. - - Na de programma heading volgt een blok waarin constantes, - types en variabelen worden gedeclareerd/gereserveerd. Het is - bij PASCAL zo dat je ALLE variabelen die je in het programma - gebruikt van te voren gedefinieerd (wat is het) en - gedeclareerd (hoe heet het) moet hebben. Dus niet zoals bij - BASIC "Oh, ik heb nog een variabele nodig. Laat ik maar iets - nemen." - - Na dit blok volgt er een blok waarin PROCEDURE's en - FUNCTION's gedeclareerd worden. Deze functies en procedures - zijn ook weer bloksgewijs opgebouwd en wel hetzelfde als een - programma. Dus ook met (functie/procedure) naam (en I/O - parameters), variabele blok, functie/procedure blok en een - hoofd blok. Hier zal ik ter zijner tijd nog uitgebreid op - terugkomen. - - Na al deze voorbereidende declaraties en definities, volgt - dan het uiteindelijke hoofdprogramma tussen de gereserveerde - woorden BEGIN en END, gevolgt door een punt. Deze punt is - voor de compiler het teken dat het programma klaar is. - - Voor deze keer wil ik besluiten met 2 programma's. Het eerste - programma CD's vind je zowel als tekstfile alsook als - gecompileerde versie (.COM file) op de FutureDisk. Het tweede - programma vind je hierbeneden. Bekijk beide programma's eens - en probeer eens te doorgronden wat ze doen. Bij onderstaand - programma mag dat geen problemen opleveren, terwijl dat bij - het programma CD's wel het geval zal zijn (behalve voor de - echte freaks onder ons). - - In de volgende afleveringen zal ik alle belangrijke elementen - van PASCAL de revue laten passeren (met veel voorbeelden EN - opgaves). Daarna zal ik recursie behandelen (ja, dat is heel - leuk) en als laatste zal ik nog aangeven wat TURBO PASCAL - precies inhoud (beter gezegt wat kan TURBO PASCAL wat - (standaard) PASCAL niet kan). - - Hier volgt een voorbeeld programma in PASCAL : -``` - PROGRAM simpel (INPUT,OUTPUT); - - VAR - Getal_1 : integer; - Getal_2 : integer; - Som : integer; - - PROCEDURE invoer_getal(VAR getal:integer); - - BEGIN (* invoer_getal *) - Write('Voer een getal in : '); - Readln(getal); - Writeln; - END; (* invoer_getal *) - - BEGIN (* hoofdprogramma *) - Writeln('Voorbeeld programma bij PASCAL-cursus (1)'); - Writeln('op de FutureDisk.'); - Writeln; - Writeln('Gemaakt door :'); - Writeln(' Jeroen ''KUBIE'' Smael'); - Writeln(' Galopiahof 6'); - Writeln(' 6215TK Maastricht'); - Writeln(' 043-437778'); - Writeln; - Writeln; - invoer_getal(Getal_1); - invoer_getal(Getal_2); - Som:=getal_1+getal_2; - Writeln(Getal_1:1,' + ',Getal_2:1,' = ',Som:1); - Writeln; - END. (* hoofdprogramma *) -``` -Jeroen 'PASCAL is leuk' Smael - - P.S. (1) Veel plezier met het uitpluizen van beide - programma's. - (2) Om beide programma's (uberhaupt elk PASCAL-programma) - te compileren heb je een PASCAL-compiler nodig. ik - vertrouw er echter op dat iedereen wel zoiets thuis - heeft liggen (op een oude floppie). - (3) Voor de echte freaks : Ik behandel alleen standaard - PASCAL. Het is namelijk een kwestie van een paar - functies bijleren als je overstapt van PASCAL naar - TURBO PASCAL. \ No newline at end of file diff --git a/Future Disk/32/Pascal cursus 2 EN.md b/Future Disk/32/Pascal cursus 2 EN.md deleted file mode 100644 index 1ac097c..0000000 --- a/Future Disk/32/Pascal cursus 2 EN.md +++ /dev/null @@ -1,83 +0,0 @@ -# Pascal Course (2) - - Let's start programming. This course will handle - variables. One of the main differences between BASIC - and PASCAL is that in PASCAL you need to declare every - variable you use before using it. This is to tell the - compiler that you are going to use this variable AND to - tell the compiler how you are going to use it. That's right, - you need not only tell the compiler that you are going to use - a variable but also what kind of variable it is (integer, - real, etc). An example (the variable declaration is started - using the reserved word VAR): - - VAR - counter : integer; - value : real; - status : boolean; - - First use the reserved word VAR. Then on the next lines state - the name of the variable followed by a colon and it's type, - follow by a semi colon. The only restriction for variable - names is that they may not be a reserved word (like BEGIN, - END, VAR, etc). - - These are the standard types: - - - boolean (can be TRUE or FALSE) - - byte (no need to explain) - - integer (16 bit value, also called word) - - longint (32 bit value, also called longword) - - real (a not integer value) - - char (an ascii character) - - string (multiple characters) - - text (a file containing characters) - - These are all the standard types included in the modern - PASCAL versions. The last two (string and text) where not - included in the early versions of PASCAL, so check the - documentation of your compiler before using them. You can - also make your own variable types, but I will come to that in - a later course. - - How to use the variables? Here are some examples: - - value:=2; - character:='A'; - counter:=counter+1; - - Assigning a value to a variable is very simple. First name - the variable you want to assign the value to, then place the - 'equals' sign (:=) and then name the value to assign. The - last works just as in basic, the only restriction is that the - type may not change, e.g. don't assign a real to an integer. - - Besides the normal operators (+, -, *, (), AND, OR, XOR, - NOT), there are also 'functions' like CHR, ORD, ROUND, TRUNC, - ABS, ARCTAN, COS, EXP, FRAC, INT, LN, SIN, SQR, SQRT, etc. - Most of them you already know if you program in BASIC. If you - don't know them, then read a book about PASCAL. All of these - functions can be used, but again, DON'T CHANGE THE TYPE. - - Good to remember is that, when using integers, there are two - special functions you can use when dividing. Use DIV to - divide, and use MOD to get what's left after the division. - - That's it for this course. I will leave you with an - assignment. I will always try to leave you with an - assignment, because the only way of learning a computer - language, is by programming in the language. - - Assignment: - Write a program that asks for three prices of products. The - program must then calculate the total price with tax, the - total price without tax, the tax of each product and the - total tax. - - Use Readln(variable) to read a variable from the keyboard, - and use Writeln(variable) to write a variable to screen. - - Have fun and if you send your solution to me, I will ensure - that your solution is published next time. - -Jeroen 'Just program it' Smael \ No newline at end of file diff --git a/Future Disk/32/Pascal cursus 2 NL.md b/Future Disk/32/Pascal cursus 2 NL.md deleted file mode 100644 index db7eba8..0000000 --- a/Future Disk/32/Pascal cursus 2 NL.md +++ /dev/null @@ -1,159 +0,0 @@ -# Pascal Course (2) - - Wat is die Koen toch een etter. Nauwelijks ben ik een PASCAL - cursus begonnen of hij begint al met klagen. Vorige keer had - ik een leuke programmaatje op de disk laten zetten om je CD's - beter op te kunnen nemen, maar nee, voor meneer Dols is het - weer niet goed. - - Koen : Kan ik niet aangeven dat ik een 60 bandje heb? - Jeroen : Nee Koen, dat kan niet, dat was wat veel werk. - Koen : Wat is dat dan voor een stom programma, zorg er maar - voor dat dat volgende keer verbeterd is! - - Tja, en ik als goede onderdaan (Sahib, sahib) heb dat dus ook - maar gedaan. Ik hoop dus maar dat hij dit keer niets te - zeiken heeft(NvdR: ik heb thuis ook nog 100 minuten bandjes - Jeroen!) - - Maar genoeg over onze kleine sadist Koen. Nu gaan we over - naar het echte werk: programmeren. Als ik mij goed kan - herinneren, dan hebben we het vorige keer over de globale - structuur van PASCAL gehad. Nu gaan we het over variabelen - hebben. - - Een groot verschil tussen BASIC en PASCAL is dat het in - PASCAL verplicht is om alle variabelen die je gebruikt van te - voren aan te melden en te specificeren. Wat ik hiermee bedoel - is dat je de compiler duidelijk maakt hoe je variabelen heten - (jan, piet of klaas) en wat voor variabelen het zijn. Een - variabele declaratie zou er als volgt kunnen uitzien (de - variabele declaratie moet altijd vooraf gegaan worden door - het gereserveerde woord VAR): - - VAR - teller : integer; - getal : real; - status : boolean; - - De opbouw van deze declaratie mag wel duidelijk zijn. Eerst - komt er het gereserveerde woord VAR. Op de volgende regels - volgt de naam van de variabele die je gaat gebruiken gevolgd - door een dubbele punt en het type van de variabele. Aan de - naam van de variabele is eigenlijk maar een grote restrictie, - de naam mag geen gereserveerd woord (zoals BEGIN, END, VAR, - etc) zijn. De dubbele punt is verplicht. Het type van de - variabele kan vanalles zijn, maar ik beperk me hier tot de - standaard types : - - - boolean (kan de waarde TRUE of FALSE hebben) - - byte (spreekt voor zich) - - integer (16 bits geheel getal, ook word) - - longint (32 bits geheel getal, ook longword) - - real (een gebroken getal, lengte hangt af van de machine) - - char (een ascii karakter) - - string (een reeks ascii karakters) - - text (een file met ascii karakters) - - De punt-comma op het einde van de regel is verplicht (bijna - alle programma regels in PASCAL worden afgesloten met een - punt-comma). Naast bovengenoemde standaard types kun je ook - zelf types ontwikkelen (dagen van de week bijvoorbeeld), maar - daar kom ik later op terug. Voor ik het vergeet, de laatste 2 - types zouden wel eens niet kunnen werken, daar ze niet vanaf - de eerste PASCAL versies ge◊mplementeerd waren. Vanaf versie - 3 of hoger zouden ze echter aanwezig moeten zijn. - - Dan komen we nu bij de toewijzingen. Deze zijn zeer - gemakkelijk : - - getal:=2; - letter:='A'; - teller:=teller+1; - - Bovenstaande voorbeelden zijn erg simpel, maar geven het - principe goed weer. Een toewijzing wordt als volgt opgebouwd: - - Als eerste komt de variabele waar iets aan toegekend moet - worden. Dan volgt een dubbele punt met een "is-gelijk" - teken (spreek := uit als 'wordt'). En als laatste volgt de - waarde die de variabele moet krijgen. Deze waarde wordt - samengesteld zoals in BASIC, met een kleine restrictie: het - type mag (uiteraard) niet wijzigen. Dus als getal eerst een - integer was, dan mag deze niet door 'getal:=1.5' veranderd - worden in een real. Genoemde toewijzing zal resulteren in - een compiler fout of een run time error. - - Naast de gebruikelijke operators (+, -, *, (), AND, OR, XOR, - NOT) zijn er ook nog functies zoals CHR, ORD, ROUND, TRUNC, - ABS, ARCTAN, COS, EXP, FRAC, INT, LN, SIN, SQR, SQRT, etc. De - meeste namen duiden op soortgelijke functies uit BASIC, voor - meer details verwijs ik naar boeken over PASCAL. Genoemde - functies kunnen gewoon gebruikt worden in een toewijzing, als - men er maar aan denkt dat het type van de hele toewijzing - gelijk moet zijn aan het type van de variabele. - - Laatstgenoemde punt impliceerd dat er twee functies moeten - zijn om een getal te delen. Waarom? Omdat delen per definitie - een gebroken getal opleverd en dat dus niet een integer is. - Gehele getallen kunnen echter wel op elkaar gedeeld worden en - daarom is er een speciale functie nodig om integers te delen. - Deze speciale functie is de DIV functie (DIVide). De logisch - bijbehorende functie is MOD (MOD geeft de rest van de - deling). - - Zo, dat was het voor deze keer. Maar voor ik jullie weer - verlaat (ooohh) geef ik jullie nog een voorbeeldje en een - opgave om zelf te maken. Van het voorbeeld programmaatje ga - ik niet veel verklappen, bekijk het maar eens en probeer - (voor- dat je het laat uitvoeren) te beredeneren wat het - doet. Het voorbeeld programmaatje staat op de disk onder - PASCAL2.PAS (dan hoeven jullie het niet over te tikken). - - De opgave daar wil ik iets anders mee doen. Als iemand zo gek - is om het te proberen, het op te lossen en de oplossing op te - sturen, dan beloof ik die persoon dat zijn oplossing volgende - keer geplaatst wordt. En om het nog aantrekkelijker te maken - vermelden we de naam van de persoon die de oplossing heeft - ingestuurd (HÇ Koen, wedje dat nu niemand meer iets instuurt. - Kun je tenminste niet weer kankeren dat je niet alles op de - disk kunt plaatsen wegens plaatsgebrek). - - Zo, genoeg getypt, nu de opgave : - Schrijf een programma dat om 3 netto prijzen van artikelen - vraagt. Bereken aan de hand van die prijzen : De BTW per - artikel, het totaal betaalde BTW bedrag, de totale BRUTO en - NETTO prijs van de drie artikelen. - - Aangezien ik nog niets heb gezegd over in- en uitvoer van - variabelen via toetsenbord en beeldscherm, verwijs ik naar - het voorbeeld programma. Door dit goed te bekijken moet het - mogelijk zijn om iets soortgelijks te construeren. - - Veel plezier en tot volgende keer, - -Jeroen 'KUBIE' Smael -Galopiahof 6 -6215TK Maastricht -Tel : 043-3437778 ('s weekends) -Tel : 040-2261521 (door de week) - -Stuur de oplossingen van de puzzle ook naar dit adres!! - - P.S. (1) Om een nieuwe programmeertaal te leren moet je zelf - een heleboel oefenen en uitzoeken, daar leer je - tenslotte het meeste van. Daarom kauw ik niet alles - voor, maar laat een heleboel aan jezelf over. - (2) Boeken die je kunt raadplegen zijn onder de VELE - andere : K.L. Boon / PASCAL voor iedereen / Kluwer / - ISBN 90.201.1425.5 --- Findley / PASCAL Inleiding - tot gestructureerd programmeren / Kluwer / ISBN - 90.201.1991.5 - (3) Let ook op de programmeerstijl die ik in het - voorbeeldprogramma gebruik. Er is geen standaard - voor, maar mijn stijl is wel gestructureerd en dat - bevorderd de leesbaarheid. - (4) Dankzij Koen staat er dus ook een verbeterde versie - van het CD programma op de disk (CD2.PAS / CD2.COM). - Veel plezier daarmee (nog iets te mekkeren, Koen?). - (NvdR: Ja, Jeroen: Bl◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊h!) \ No newline at end of file diff --git a/Future Disk/32/Screen 4.md b/Future Disk/32/Screen 4.md deleted file mode 100644 index 0cb07cd..0000000 --- a/Future Disk/32/Screen 4.md +++ /dev/null @@ -1,194 +0,0 @@ -# Screen 4 - - - Bij alle besprekingen van de MSX2 video chip, wordt er altijd - aandacht besteed aan de bitmapped modes, screen 5 tot en met - acht, maar nooit aan de mogelijkheden van Screen 4. - Waarschijnlijk is dit, omdat Screen 4 te zeer een MSX1 - verleden heeft. Toch zijn de mogelijkheden van deze - schermmode groot en kunnen er leuke dingen mee gedaan worden. - -## Opbouw - - Screen 4 is een pattern screen. Dit wil zeggen, dat het - scherm niet bestaat uit pixels, maar wordt opgebouwd uit - informatie uit verschillende tabellen. Dit klinkt erg - moeilijk, maar het komt erop neer dat wanneer je pixel (0,0) - wit wil maken, je eerst in de patroon tabel een volgend - patroon aanmaakt: - - &b10000000 - &b00000000 - &b00000000 - &b00000000 - &b00000000 - &b00000000 - &b00000000 - &b00000000 - - Plaatsen we dit patroon in het begin van de eerste - patroontabel (er zijn er meer) dan krijgt dit patroon nummer - nul. Vervolgens vullen we de kleur tabel met dit patroon: - - &hf0 - &h00 - .. (volmaken tot de acht) - &h00 - - En tot slot plaatsen we in de naam tabel op de eerste positie - een nul en we zien een witte pixel. - Hieruit blijkt al dat het dus een stuk moeilijker is om te - tekenen op Screen 4. - - Samenvattend komen we nu uit bij de drie tabellen: - - -## PATROON TABEL - - De locatie van de patroontabel in het videogeheugen kan - worden ingesteld middels register 4: - - Msb 7 6 5 4 3 2 1 0 - Reg 4 0 0 A16 A15 A14 A13 1 1 - - Als je de patroon tabel dus op adres nul wil laten beginnen, - dan laad je register 4 met %b11. - - De patroontabel bestaat uit drie blokken van elk 256 - patterns. Hiermee is het mogelijk om het gehele scherm te - vullen. Het eerste block bevat de informatie voor de de - bovenste 64 beeldlijnen (0-63). Hieruit volgt al ÇÇn van de - grappige eigenschappen van Screen 4, als je een patroon - binnen lijn 0-63 en lijn 64-127 wil gebruiken, dan moet je - dit patroon twee keer defini◊ren. - - De opbouw van het patroon ziet er als volgt uit: - &01 - Aanvullen tot acht - &00 - - Zoals al duidelijk wordt, kun je maar twee kleuren in een - acht bij acht blokje gebruiken. Je hebt enkel variatie 1 en - 0. Dankzij de kleuren tabel echter kun je per lijn de kleur - veranderen. Het idee komt overeen met dat van sprites. - - Nog een leuke bij de patroontabel. Toen ik met vdp23 in de - weer ging op een Screen 4 scherm, kreeg ik met geen - mogelijkheid de lijnen van (192-255) gevuld. Maar toen ik - effe naar de layout keek en erg simpel even wat adressen in - het video geheugen opschoof, viel op dat de patroontabel - eigenlijk uit vier blokken bestaat: (0-63),(64-127),(128- - 191),(192-255). Maar omdat dit alleen kan als je meer dan 16k - video geheugen hebt, wordt dit nooit in een of ander databoek - vermeld. - - -## KLEURENTABEL - - De kleurentabel bepaalt welke kleuren geassoci◊erd moeten - worden met de nul en een in de patroon tabel. De plaats van - de kleurentabel bepaal je met registers 3 en 10: - - Msb 7 6 5 4 3 2 1 0 - Reg 3 A13 1 1 1 1 1 1 1 - Reg 10 0 0 0 0 0 A16 A15 A14 - - De kleurentabel bestaat opnieuw uit drie (vier dus) blokken - en is per blok als volgt opgebouwd: - - &00 - aanvullen tot acht - &00 - - Waarbij de eerste nibble de kleur van de als 1 gedefini◊erde - patronen bepaald en de laagste nibble de kleur van de als 0 - gedefini◊erde. Dit kun je per lijn wijzigen. - -## NAAM TABEL - - Nu hebben we de kleuren en de patronen, dan volgt tot slot - nog de naam tabel. De plaats van deze tabel in het geheugen - kun je bepalen met register 2. - - Msb 7 6 5 4 3 2 1 0 - Reg 2 0 A16 A15 A14 A13 A12 A11 A10 - - In deze tabel bepaal je op welke plaats je gedefini◊erde - patronen terecht moeten komen. Positie nul in de tabel komt - overeen moet coordinaat (0,0). Positie ÇÇn komt overeen moet - (8,0) enz. In deze bytes zet je het patroon nummer. Je hoeft - je geen zorgen te maken om de kleurentabel, want deze is - automatisch gekoppeld aan de patroontabel. Uiteraard bestaat - deze tabel ook weer uit drie (vier) delen. - - Zo, nu hebben we alle data van screen4 besproken, laten we - eens kijken hoe het in de praktijk werkt door middel van ÇÇn - van de meest aansprekende voorbeelden: Space Manbow. - - Als we Space Manbow opstarten moeten we even door wat scherm - 5 plaatjes heen en komen we in het prachtige speelscherm. - - Wat zien wij nu: - - Een stilstaande bovenkant (screen 5, line interrupt) - Een sterren scroll (screen4) - Een scrollend middenveld (Screen 4) - Een rap scrollend benedenveld (Screen 4) - Een lading sprites. - - Geweldig! - - De sterretjes worden wel heel simpel gedaan, door voortdurend - het patroon te wijzigen. Een simpele RLCA instructie doet - hier wonderen. Het middenveld wordt gescrolled door de - naamtabel voortdurend te verplaatsen en tot slot de onderste - lijn wordt bewerkt door gewoon twee keer zo snel de naam - tabel door te schuiven. - - Zoals je al altijd gezien had, is het resultaat verbluffend, - het spel lijkt eerder van de SuperNes te komen, dan van een - simpele MSX. - Aangezien Konami een stel designers in dienst had die een - lange staat van dienst op de MSX 1 achter de rug hadden, is - er goed gebruik gemaakt van de mogelijkheden van Screen 4. - Als je goed kijkt, valt je namelijk op dat er echt gespeeld - is met de twee kleuren per 8x8 blokje. Het is vergelijkbaar - met het ontwerpen van sprites. - Ook in de hogere levels is leuk ingehaakt op de mogelijkheden - van pattern screens. Zo noem ik de laserstralen van het boss - monster in het laatste level. Als je dat met een line - commando in screen 5 zou willen doen, zou dat heel erg traag - worden. Op schermpje vier edit je een patroontje en met wat - gespeel in de naamtabel heb je schermvullende actie. - - Een ander leuk voorbeeld van Screen 4 is FireHawk. Het intro, - met de naar achter vliegende letters is ook op scherm vier - gemaakt. Waarom? Omdat scherm vier snel is en het weinig - geheugen in beslag neemt. Ook het hele spel loopt in Screen - 4 - en scrollt met stappen van 8 bij 8. - - Waarom gebruikt dan niemand scherm 4? Simpel: - - ? Je moet een heel goede tekenaar zijn - ? Je moet een heel goed tekenprogramma hebben - ? Je moet heel goede dataveld editors hebben - ? Je moet iemand met een MSX1 verleden zijn - - Aangezien er bijna niemand aan deze eisen voldoet, maakt dan - ook niemand iets op Screen 4. Alleen Jan van Valburg heeft - ooit twee Screen 4 spellen gemaakt, Gianna Sisters en - Retaliator. Oh ja, Çn ANMA natuurlijk met Troxx. - - Dus, als je ooit nog een Space Manbow wilt maken: leer teke- - nen met beperkingen en gebruik allerlei truukjes om de - mensen te laten geloven dat ze naar een Super Nes zitten te - kijken. - - Succes - - -Jan-Willem van Helden - - P.S. Ik probeer op de volgende FD nog iets leuks te doen met - Screen 4. Let op! \ No newline at end of file diff --git a/Future Disk/33/Advanced Basic 3.md b/Future Disk/33/Advanced Basic 3.md deleted file mode 100644 index b2e2cf9..0000000 --- a/Future Disk/33/Advanced Basic 3.md +++ /dev/null @@ -1,92 +0,0 @@ -Arjan vervolgt zijn cursus Advanced Basic... - Cursus Advanced BASIC (3) - - - Advanced BASIC heeft een aantal extra diskcommando's die het - leven heel wat makkelijker maken voor de BASIC-programmeur. - - Een van die commando's is _DISKRD(drive,start,aantal,adres). - Dit commando laadt een aantal sectoren achterelkaar. De - variabele drive staat hier voor de drivenummer (0 = A, 1 = B - enz.), start is de eerste sector, aantal is het aantal - sectoren en adres is het adres waar de inhoud van de gelezen - sectoren terecht moet komen. - - Als er een _DISKRD is, is er natuurlijk ook een _DISKWRT, - die een aantal sectoren achter elkaar schrijft. De syntax is - hetzelfde als bij _DISKRD. - - Een voorbeeldje: - - 10 _DISKRD(0,0,16,&H9000) - 20 _DISKWRT(1,0,16,&H9000) - RUN - - Dit programma laadt de eerste 16 sectoren van drive A en - slaat ze op op drive B. - - -BESTANDEN - - Bepalen welke bestanden er op een diskette staan is altijd - lastig geweest onder BASIC. Advanced BASIC heeft daar 3 - commando's voor. Ten eerste is er _FILENAME(VAR$), welke - bepaald naar welke bestanden er moet worden gezocht. VAR$ - MOET overigens minstens 11 letters lang zijn en het *-teken - mag niet gebruikt worden. - - Om nu het eerste bestand dat op de diskette staat te - achterhalen, is er _SFFILE(VAR$) (VAR$ is weer minstens 11 - tekens lang). De eerste filenaam die voldoet aan de met - _FILENAME(VAR$) opgegeven filenaam, komt nu in VAR$ terecht. - Alle volgende filenamen kunnen met _SNFILE(VAR$) geladen - worden. Als er 2 keer achter elkaar dezelfde filenaam - gelezen is, heb je alle filenamen gehad. - - Een voorbeeld: - - 10 _FILENAME("????????BAS") - 20 F$=SPACE$(11):G$=F$ - 30 _SFFILE(F$):IF G$=F$ THEN END - 40 PRINT F$:G$=F$ - 50 _SNFILE(F$):IF G$=F$ THEN END - 60 GOTO 40 - RUN - - Dit programma laat alle bestanden met de extensie .BAS zien. - - -DRIVES - - Het aantal aangesloten drives is te bepalen met het commando - _NDRIVES(adres). Het aantal drives komt dan op het opgegeven - adres terecht. - - De huidige drive is op te vragen met _GETDRIVE(adres). Als - je de huidige drive wilt veranderen, kun je _SETDRIVE(drive) - gebruiken. - - Een voorbeeld: - - 10 _GETDRIVE(&H9000) - 20 PRINT "De huidige drive is ";CHR$(PEEK(&H9000+65)) - 30 _NDRIVES(&H9000) - 40 PRINT "Er zijn";PEEK(&H9000);" drives aangesloten" - 50 PRINT "Welke drive moet de default-drive worden?"; - 60 INPUT "In letters graag";D$ - 70 D=ASC(D$) OR 32:D=D XOR 32:D=D-65 - 80 _SETDRIVE(D) - RUN - - Dit programma geeft de defaultdrive en het aantal drives - weer en daarna mag je de nieuwe defaultdrive zelf bepalen. - - -TOETJE - - Als toetje zijn er nog de commando's _VERIFYON en _VERIFYOFF - welke de controle op schrijffouten respectievelijke aan- en - uitzetten. - - -Arjan Bakker diff --git a/Future Disk/33/Assembly Cursus 2.md b/Future Disk/33/Assembly Cursus 2.md deleted file mode 100644 index 20831ef..0000000 --- a/Future Disk/33/Assembly Cursus 2.md +++ /dev/null @@ -1,109 +0,0 @@ - De assembly cursus gaat eindelijk verder... -ASSEMBLY CURSUS (2) - - - Hier is dan eindelijk het tweede deel van de assembly - cursus. Dit maal bespreek ik een string-search routine. De - routine is zo simpel mogelijk gehouden door wildcards etc. - gewoon niet toe te staan. Het moet echter simpel zijn om de - wildcard '?' te implementeren. - - -DE INVOER - - De routine heeft 3 variabelen nodig, namelijk het adres waar - met zoeken moet worden begonnen (HL), het aantal te - onderzoeken bytes (BC) en het beginadres van de te zoeken - string (DE). De te zoeken string moet afgesloten worden met - #FF, evenals de strings in het geheugen. - - -DE ROUTINE - - Hier komt dan de routine, met tussendoor wat uitleg. - - SEARCH: PUSH DE - INC HL - - SEARCH initialiseert de zoek-routine. DE moet bewaard - worden, omdat deze wordt gebruikt om bij te houden op welke - plek in de string we zitten. CPI verhoogt HL altijd, maar - als de bytes niet hetzelfde zijn, moet dat juist niet. - Daarom wordt HL alvast verhoogd, omdat HL in STRSRC verlaagt - MOET worden. - - STRSRC: POP DE - PUSH DE - DEC HL - LD A,(DE) - - SRCHF: CPIR - JP Z,FOUNDF - - STOP: LD A,255 - POP DE - RET - - Eerst wordt de pointer weer opgehaald en bewaard. HL wordt - verlaagd omdat CPI HL altijd verhoogt, terwijl dat juist - niet altijd nodig is. Dan wordt het eerste teken van de - string geladen en CPIR zoekt dan net zolang totdat het teken - gevonden is. Als het teken gevonden is, wordt er gesprongen - naar de routine die de volgende bytes onderzoekt en anders - stopt het programma met 255 in de accu om aan te geven dat - de string niet gevonden is. - - FOUNDF: LD (STRADR),HL - - Adres van string wordt bewaard, omdat de string niet gelijk - hoeft te zijn als de zoekstring. - - INC DE - LD A,(DE) - SRCHN: CPI - JP NZ,STRSRC - - Volgende teken wordt geladen en vergeleken. Als ze niet - gelijk zijn, wordt er teruggegaan naar de routine die het - eerste teken zoekt. - - LD A,B - OR C - JP Z,STOP - - Als alle bytes geweest zijn, stopt het programma. - - INC DE - - Volgende teken. - - LD A,(DE) - CP #FF - JP NZ,SRCHN - LD A,(HL) - CP #FF - JR NZ,STRSRC - - Er wordt gekeken of de zoekstring aan het einde is. Als dat - niet zo is, wordt er verder gegaan met vergelijken. Als dat - wel zo is, wordt er gekeken of de string in het geheugen ook - aan het einde is. Als dat niet zo is, wordt er overnieuw - begonnen met zoeken. - - XOR A - LD HL,(STRADR) - DEC HL - POP DE - RET - - STRADR: DEFW 0 - - Accu wordt 0 om aan te geven dat het zoeken gelukt is. Het - adres van de string wordt geladen en DE wordt teruggehaald - ivm met RET. - - Zo, dit was de routine. Voor de mensen die het willen - gebruiken, staat de routine ook op disk onder de naam - STRSRCH.ASM. Tot de volgende keer! - -Arjan Bakker diff --git a/Future Disk/33/Bits en bull.md b/Future Disk/33/Bits en bull.md deleted file mode 100644 index 4d25e1b..0000000 --- a/Future Disk/33/Bits en bull.md +++ /dev/null @@ -1,259 +0,0 @@ - Programmeercursi zat dit keer... - The lamest ML course in town... Bits and bullshit... - - - ���� - ���� - ���� - ���� - - - De DOS2.x text van deze keer was wat aan de korte kant, dus - ik ga me maar eens op ML storten. En dit keer eens wat and- - ers. We gaan het BIT commando helemaal uitdiepen. ALLES wat - we er maar over moeten weten komt deze keer aan bod. Hou je - vast dus, wat dit kon nog wel eens een flinke text worden. - - -She said byte me... - - BIT kan maar voor een ding gebruikt worden.. Om de toestand - van een byte te bepalen. Door het juiste BIT commando te ge- - bruiken kunnen we de toestand van alle bitjes in een byte - afzonderlijk bepalen. Uiteraard kan dit op vele manieren en - lang niet altijd zal BIT de handigste zijn, maar BIT heeft - wel een flink aantal mogelijkheden. - - -So I bit her... - - [BIT nummer,slachtoffer] Hierbij staat nummer voor het bit- - nummer dat natuurlijk 0 tot 7 mag zijn. Het slachtoffer van - deze bewerking kan werkelijk van alles zijn maar daar komen - we zometeen op terug. BIT doet maar een belangrijk ding; de - zero-flag wel of niet zetten... En dat wilden we nu net van - het slachtoffer weten. - - -I must have misunderstood... - - Eerst alle mogelijkheden op een rijtje. Ik zal eerst de mo- - gelijke BIT instructies maar eens op een rijtje zetten. Dan - komt de onafhankelijke beschrijving later. - - BIT b,(HL) - BIT b,(IX + n) - BIT b,(IY + n) - BIT b,r - - -'Coz she popped me dead... - - Nou, dat viel toch reuze mee of niet??? Laten we eerst alle - instructies eens afzonderlijk onder de loep nemen, dan komt - daarna de volledige lijst met tijdsduur etc wel... - - -BIT b,(HL) - - Bit b van de geheugen locatie geadresseerd door HL wordt ge- - test en de zero-flag wordt overeenkomstig met het resultaat - geset. De bbb in de object codes komen overeen met het geko- - zen bit voor de test. - - OBJ CODE: Byte 1: %11001011 ($CB) - Byte 2: %01bbb110 ( - ) - - -BIT b,(IX + n) - - Bit b van de geheugen-locatie geaddresseerd door de inhoud - van register IX plus de verplaatsing [n] wordt getest en de - zero-flag wordt overeenkomstig met bit b geset. De n in de - object code staat voor de opgegeven verplaatsing. - - OBJ CODE: Byte 1: %11011101 ($DD) - Byte 2: %11001011 ($CB) - Byte 3: %nnnnnnnn ( n ) - Byte 4: %01bbb110 ( - ) - - -BIT b,(IY + n) - - Bit b van de geheugen-locatie geaddresseerd door de inhoud - van register IY plus de verplaatsing [n] wordt getest en de - zero-flag wordt overeenkomstig met bit b geset. - - OBJ CODE: Byte 1: %11011101 ($FD) - Byte 2: %11001011 ($CB) - Byte 3: %nnnnnnnn ( n ) - Byte 4: %01bbb110 ( - ) - - - BIT b,r - - Bit b van register r wordt getest en de z-flag wordt over- - eenkomstig geset. De r in de object code staat voor de bin- - aire code achter elk register. - - r: A %111 B %000 C %001 D %010 E %011 H %101 L %101 - - OBJ CODE: Byte 1: %11001011 ($CB) - Byte 2: %01bbbrrr ( - ) - - -And that's it... - - En dat was het al weer. Tijd dus om de timing van deze type - BIT instructies eens te bekijken. Ik zal de timing in mach- - ine cycli geven en in T-States. Om dus de duur van een in- - structie te berekenen moet het aantal T-States vermenigvul- - digd worden met de duur van een cyclus... De M-Cycli hebben - daar dus niets mee te maken. De snelheid in miliseconden is - variabel (ligt aan het type processor; Z80a/Z80b/Z80h/R800) - dus die geef ik niet op. De R800 is overigens een apart ge- - val... Daar gaat het namelijk niet om de clock snelheid van - 7MHz maar om het feit dat de R800 ook nog eens minder Cycli - nodig heeft om een BIT instructie uit te voeren... Zeker de - instructie met de index registers gaan flink wat sneller!!! - Hier is de R800 dus op twee punten sneller dan de Z80a. Ten - eerste omdat de clock snelheid hoger ligt en ten tweede om- - dat de R800 minder T-States nodig heeft. - - - | Instructie | M Cylci | T States | - +------------------+-------------+---------------+ - | BIT b,(HL) | 3 M Cycli | 12 T States | - | BIT b,(IX + n) | 5 M Cycli | 20 T States | - | BIT b,(IY + n) | 5 M Cylci | 20 T States | - | BIT b,r | 2 M Cylci | 08 T States | - - -That's all folks... - - En dan zit het er echt op!! Op een ding na natuurlijk... De - lijst van alle mogelijke bit instructies en hun object code - natuurlijk. Om de routine van Smael niet al te erg te tar- - ten zal ik hiervoor maar een aparte text typen, lees dus in - deel twee verder voor alle instucties, met alle OBJ codes. - - Voor nu, slaap lekker, en tot de volgende FD... - - - Dhr Keizer...ah whatever ik weet het ook niet - To byte, bit, bit.... - - ���� - ���� - ���� - ���� - - - Okay, beloofd is beloofd, alle mogelijke instructies, met - alle objectcodes... Tja, hoe krijg je zo'n diskmagazine an- - der vol tegewoordig. (Hint: Met lezersbrieven...) Oh wacht, - laat ik wel oppassen met wat ik zeg.. ik ga natuurlijk niet - alle 256 mogelijke verplaatsingen bij de indexregisters op- - geven; dan wordt Smael z'n routine echt depressief... - - BIT 0,(HL) CB 46 - BIT 0,(IX+d) DD CB 05 46 - BIT 0,(IY+d) FD CB 05 46 - BIT 0,A CB 47 - BIT 0,B CB 40 - BIT 0,C CB 41 - BIT 0,D CB 42 - BIT 0,E CB 43 - BIT 0,H CB 44 - BIT 0,L CB 45 - - BIT 1,(HL) CB 4E - BIT 1,(IX+d) DD CB 05 4E - BIT 1,(IY+d) FD CB 05 4E - BIT 1,A CB 4F - BIT 1,B CB 48 - BIT 1,C CB 49 - BIT 1,D CB 4A - BIT 1,E CB 4B - BIT 1,H CB 4C - BIT 1,L CB 4D - - BIT 2,(HL) CB 56 - BIT 2,(IX+d) DD CB 05 56 - BIT 2,(IY+d) FD CB 05 56 - BIT 2,A CB 57 - BIT 2,B CB 50 - BIT 2,C CB 51 - BIT 2,D CB 52 - BIT 2,E CB 53 - BIT 2,H CB 54 - BIT 2,L CB 55 - - BIT 3,(HL) CB 5E - BIT 3,(IX+d) DD CB 05 5E - BIT 3,(IY+d) FD CB 05 5E - BIT 3,A CB 5F - BIT 3,B CB 58 - BIT 3,C CB 59 - BIT 3,D CB 5A - BIT 3,E CB 5B - BIT 3,H CB 5C - BIT 3,L CB 5D - - BIT 4,(HL) CB 66 - BIT 4,(IX+d) DD CB 05 66 - BIT 4,(IY+d) FD CB 05 66 - BIT 4,A CB 67 - BIT 4,B CB 60 - BIT 4,C CB 61 - BIT 4,D CB 62 - BIT 4,E CB 63 - BIT 4,H CB 64 - BIT 4,L CB 65 - - BIT 5,(HL) CB 6E - BIT 5,(IX+d) DD CB 05 6E - BIT 5,(IY+d) FD CB 05 6E - BIT 5,A CB 6F - BIT 5,B CB 68 - BIT 5,C CB 69 - BIT 5,D CB 6A - BIT 5,E CB 6B - BIT 5,H CB 6C - BIT 5,L CB 6D - - BIT 6,(HL) CB 76 - BIT 6,(IX+d) DD CB 05 76 - BIT 6,(IY+d) FD CB 05 76 - BIT 6,A CB 77 - BIT 6,B CB 70 - BIT 6,C CB 71 - BIT 6,D CB 72 - BIT 6,E CB 73 - BIT 6,H CB 74 - BIT 6,L CB 75 - - BIT 7,(HL) CB 7E - BIT 7,(IX+d) DD CB 05 7E - BIT 7,(IY+d) FD CB 05 7E - BIT 7,A CB 7F - BIT 7,B CB 78 - BIT 7,C CB 79 - BIT 7,D CB 7A - BIT 7,E CB 7B - BIT 7,H CB 7C - BIT 7,L CB 7D - - - Nou, nou!! Dat dat een flink stuk typen was mag wel duide- - lijk zijn. Och mensen wat een klus. Maar goed, dat was het - waar, want dergelijke tabelletjes kunnen wel degelijk heel - handig zijn. Gelukkig maar dat een print optie in de FD zit - want overschijven zou een flinke klus zijn... Tenzij je na- - tuurlijk Patrick heet en flink getrainde armen hebt... - - Maar goed, dit besluit dus de bit-cursus. De volgende keer - gaan we vast wel verder met iets, maar waar over?? - - -Tobias Keizer diff --git a/Future Disk/33/Pascal 3.md b/Future Disk/33/Pascal 3.md deleted file mode 100644 index 8258825..0000000 --- a/Future Disk/33/Pascal 3.md +++ /dev/null @@ -1,150 +0,0 @@ -Dit is een poging om de langste scroll regel ooit op de FutureDisk te maken (NvdR: dat is mislukt Jeroen, ik heb hem afgekapt!) - - PASCAL (3) - - - ���� Welcome to the third PASCAL course. Ofwel, hallo, dit - ���� is de derde PASCAL cursus op de FD. Het mag dan wel - ���� FutureDisk 33 zijn, maar aangezien de PASCAL cursus pas - ���� zijn derde nummer ingaat zou alles dus helemaal okie - dokie moeten zijn. Wat een gezeur h�! Ik zal maar be- - ginnen, voor ik nog meer onzin uitkraam. - - Vorige keer heb ik het over Koen gehad (helemaal in het begin) - en ja hoor, hij had weer iets te zeiken, dus nu even mijn - antwoord: "Ja Koen, je kunt ook 100 minuten bandjes door mijn - programma laten uitrekenen.". Zo, dat is ook weer opgelost. - (NvdR: ja stomme ezel, dat had ik ook al door!) - - Nu even echt serieus. Deze keer ga ik lussen bespreken. In - PASCAL zijn drie soorten lussen: FOR-TO-DO, REPEAT-UNTIL en - WHILE-DO. Uit de namen kan al ��n en ander afgeleid worden. - Maar ik zal de verschillende lussen met een voorbeeld - behandelen. - - Stel ik wil de getallen 1 t/m 10 op het scherm toveren. Hoe - doe ik dat? Hier komen de drie mogelijkheden: - -FOR-TO-DO: - - PROGRAM ForNext (input,output); - - VAR - teller : integer; - - BEGIN - FOR teller := 1 TO 10 DO - writeln(teller); - END. - -REPEAT-UNTIL: - - PROGRAM RepeatUntil (input,output); - - VAR - teller : integer; - - BEGIN - teller := 0; - REPEAT - teller := teller + 1; - writeln(teller); - UNTIL teller = 10 - END. - -WHILE-DO: - - PROGRAM WhileDo (input,output); - - VAR - teller : integer; - - BEGIN - teller := 0; - WHILE teller < 10 DO - BEGIN - teller := teller + 1; - writeln(teller); - END; - END. - - Dat waren ze. Maar nu de uitleg. In het eerste voorbeeld - (FOR-TO-DO) zie je, dat de variabele "teller" van 1 t/m 10 zal - lopen. Er staat tenslotte dat de teller zal lopen van 1 tot en - met 10, en zolang moet je teller afdrukken. Een FOR lus kan - niet worden onderbroken (voor de echte crack wel, maar dat is - met een GOTO en dat is weer niet gestructureerd en dus niet - netjes). Een FOR lus loopt altijd van onder- tot bovengrens. - Nu denk je natuurlijk: Ik wil ook van 10 naar 1 kunnen lopen, - dat kan, maar dan moet je DOWNTO in plaats van TO gebruiken. - Voor de goede orde: Als de ondergrens groter is dan de - bovengrens (FOR teller := 2 TO 1 DO) dan gebeurt er dus - niets. - - Het tweede voorbeeld (REPEAT-UNTIL) werkt heel anders. Hier - wordt de lus op een bepaalde conditie verlaten. In het - voorbeeld staat dan ook HERHAAL ... TOTDAT teller=10. Zolang - teller niet 10 is, gaat de lus door. Probeer maar eens wat er - gebeurt als je de regel "teller := teller + 1;" weglaat. Je - zult zien dat de lus eindeloos doorgaat; teller wordt ook - nooit 10. - - Het verschil met het tweede en derde voorbeeld is eigenlijk - minimaal. Ook hier wordt de lus verlaten bij een bepaalde - conditie (teller=10), alleen wordt hier eerst gecontroleerd en - daarna pas beslist of de lus doorlopen moet worden. Het grote - verschil is dan ook dat de REPEAT-UNTIL minimaal 1 maal - doorlopen wordt, terwijl dat bij de WHILE-DO niet het geval - is. - - Zo, dat was een snel overzicht van de lus functies in PASCAL. - En nu maar oefenen. Tja, ik kan het niet vaak genoeg zeggen, - veel oefenen, anders leer je het niet. Ik zal, hoewel vorige - keer niemand een reactie heeft gegeven(gek h�) (NvdR: ligt - gewoon aan jou!), ook deze keer wat opdrachten geven. - - OPDRACHTEN: - (1) Maak een programma dat alle mogelijke combinaties van 4 - (hoofd)letters op het scherm zet (doe dit met alleen - FOR-TO-DO, REPEAT-UNTIL of WHILE-DO lussen). - (2) Maak een programma dat alle priemgetallen tot een - ingegeven getal berekend (doe ook dit met alleen - FOR-TO-DO, REPEAT-UNTIL of WHILE-DO lussen). - - Voordat jullie kunnen beginnen moet ik nog even snel wat - uitleggen over compound-statements. In PASCAL is het namelijk - zo, dat na bepaalde opdrachten (FOR-TO-DO, WHILE-DO, - IF-THEN-ELSE) maar ��n opdracht mag staan. Bij de FOR-TO-DO - lus mag dus niet staan: - - WHILE teller < 10 DO - write(teller); - teller := teller + 1; - - De opdracht "write(teller)" is namelijk 1 opdracht en de - volgende opdracht "teller := teller + 1" zou pas worden - uitgevoerd als de WHILE-DO lus voorbij is (nooit(!)). Vaak is - het echter noodzakelijk dat meerdere opdrachten in een lus - worden uitgevoerd. De oplossing hiervoor is het compound- - statement. Een compound-statement is een heleboel statements - omgeven door een BEGIN en een END. Het voorbeeld zal dus - worden: - - WHILE teller < 10 DO - BEGIN - write(teller); - teller := teller + 1; - END; - - Bij het bovenstaande programma zal alles wel naar wens - verlopen. Samenvattend komt het er op neer dat als je bij - lussen (REPEAT-UNTIL is hier de bevestigende uitzondering) - meerdere statements wil laten uitvoeren, dat je die statements - moet laten voorafgaan door BEGIN en eindigen met END. - - Zo, met bovenstaande informatie moet je in staat zijn om de - zes opdrachten te maken. - - Veel plezier, - - Jeroen "In de herhaling" Smael diff --git a/Future Disk/33/Pascal 4.md b/Future Disk/33/Pascal 4.md deleted file mode 100644 index 5dbe2e0..0000000 --- a/Future Disk/33/Pascal 4.md +++ /dev/null @@ -1,148 +0,0 @@ -Dit is deel vier van de zeer interessante PASCAL cursus... - PASCAL (4) - - - ���� Programmeren is masochisme, maar wat is het lekker - ���� (NvdR:??). Nou ja, als je aan het programmeren BENT - ���� niet, maar als het werkt en die kl*t* machine doet - ���� eindelijk precies wat JIJ wilt, dat is pas een - hoogtepunt. Waarom vertel ik dit allemaal? Als eerste - omdat ik een reactie van Koen wil uitlokken (h� etter, waar - ben je) (NvdR: hiero!) en als tweede een meer belangrijke - reden (Koen is tenslotte niet belangrijk) (NvdR: moet je - iemand horen!) om je te stimuleren om toch vooral door te - gaan, want uiteindelijk lukt het wel! (dat MSX'je kan veel - meer dan je denkt). - - Deze vierde aflevering van mijn PASCAL cursus is gewijd aan - PROCEDURE's en FUNCTION's. In elke programmeertaal ontstaat op - een bepaald moment behoefte aan funkties en procedures. - Waarom? Nou, gewoon, omdat je geen zin hebt om een bepaald - stuk code dat je vaker nodig hebt (bijvoorbeeld een invoer - routine) ook vaker in te tikken. Als je het geheel ��n keer - hebt ingetikt, dan wil je het vaker gebruiken, niet alleen - omdat je maar ��n keer wil tikken, maar ook omdat dat stuk het - doet en je bij overtikken fouten kunt maken. - Wat is nu het verschil tussen FUNCTION en PROCEDURE? Het - verschil zit 'm in de uitkomst. FUNCTION heeft een uitkomst, - PROCEDURE niet. Een heel eenvoudige FUNCTION ziet er als volgt - uit: - - FUNCTION Optel(Getal1:integer;Getal2:integer):integer; - BEGIN (* Optel *) - Optel := Getal1 + Getal2; - END; (* Optel *) - - Bovenstaande funktie is dus niets. Je zou hem nooit gebruiken - in een programma, omdat optellen al standaard aanwezig is. Wel - zou je een funktie schrijven om machten te berekenen, omdat - dat niet standaard in PASCAL aanwezig is. Het voorbeeld geeft - wel duidelijk de struktuur van een funktie weer. - Als eerste staat het gereserveerde woord FUNCTION, waarna de - naam van de funktie volgt (let op; gebruik hiervoor geen - gereserveerde woorden!). Tussen haakjes volgen de variabelen - die je nodig denkt te hebben in de funktie tesamen met hun - type (dit stuk is niet verplicht, omdat je niet altijd - variabelen nodig hebt, denk hierbij aan een random funktie). - Als laatste volgt er nog het type van de uitkomst van de - funktie. - - Na deze eerste regel volgt de body van de functie, die - overigens precies gelijk is aan de body van een programma - (ook hier kun je variabelen declareren en andere funkties of - procedures maken). In het code gedeelte is slechts een ding - verplicht en dat is het toekennen van een waarde aan de - funktie (in het voorbeeld "Optel := Getal1 + Getal2"). Doe - je dit niet, dan krijg je gegarandeerd een foutmelding. - Een klasieke fout is overigens het volgende: - - Optel := 0; - FOR Teller := 1 TO 10 DO - Optel := Optel + Getal[Teller]; - - Hiermee zou je een ARRAY kunnen optellen (denk je), maar het - is verboden om de naam van de funktie (Optel) rechts van het - toekenningsteken te plaatsen en dus werkt het niet. Om het wel - aan de praat te krijgen zul je een variabele "Som" moeten - declareren en het volgende moeten doen: - - Som := 0; - FOR Teller := 1 TO 10 DO - Som := Som + Getal[Teller]; - Optel := Som; - - Zo, nu is de uitleg van een procedure een makkie (dus niet). - Eerst een voorbeeld: - - PROCEDURE Uitkomst(Getal:integer); - - BEGIN (* Uitkomst *) - Writeln('De uitkomst is : ',Uitkomst); - END; (* Uitkomst *) - - Alweer zo'n gemakkelijk voorbeeldje (anders begint Koen te - klagen dat 'ie 't nie begrijp, eikel!)(NvdR: leer jij maar - eens een tekstroutine programmeren!). Je ziet dat de struktuur - nagenoeg gelijk is. - Een procedure heeft geen uitkomst en dat blijkt uit de eerste - regel (heading). Verder mag de procedure geen waarde krijgen - (Uitkomst := 10 is dus uit den boze). Voor de rest is alles - gelijk (er mogen dus ook variabelen gedeclareerd en funkties - of procedures gemaakt worden). - - Je weet nu bijna alles van funkties en procedures, ik moet - alleen nog parameter variabelen uitleggen. Bij een funktie of - procedure geef je gewoonlijk ��n of meer variabelen mee, - alleen, je geeft ze niet mee, je copieert ze. Wat ik bedoel - is, dat de waarde die een variable bezit bij aanroep van de - funktie of procedure, wordt gecopieerd. Aanchouw het volgende - voorbeeld: - - FUNCTION T1(Getal1:integer;Getal2:integer):integer; - - BEGIN (* T1 *) - T1 := Getal1 + Getal2; - Getal1 := Getal1 * 2; - END; (* T1 *) - - En vervolgens in het hoofdprogramma de volgende opdrachten: - - A := 10; - B := 20; - Iets := T1(A,B); - - Deze funktie heeft value parameters, wat betekent dat bij de - aanroep wordt gekeken wat de waarde van de formele parameters - (A en B) is en die gecopieerd wordt naar de actuele parameters - (Getal1 en Getal2). De uitkomst is (hoe kan het anders) 30. De - vraag is echter, wat wordt A? In dit geval veranderd A NIET (A - blijft 10). De copie (Getal1) verandert, maar de formele - parameter (A) blijft gelijk, er bestaat geen link. Daarom - noemt men dit value parameters ofwel waarde parameters, alleen - de waarde wordt doorgegeven. - De andere variabelen zijn parameter variabelen. Een funktie of - procedure met parameter variabelen ziet er als volgt uit: - - FUNCTION T2(VAR Getal1:integer;Getal2:integer):integer; - - BEGIN (* T2 *) - T2 := Getal1 + Getal2; - Getal1 := Getal1 * 2; - END (* T2 *) - - Herhalen we nu de aanroep, dan veranderd A wel in 20. A wordt - nu namelijk als referentie meegegeven. Alle bewerkingen op - Getal2 vinden nu rechtstreeks plaats op A. - - Zo, dat was alles wat ik over funkties en procedures kwijt - wilde. Als oefening deze keer kun je alle voorgaande - oefeningen opnieuw doen, alleen met dit verschil dat je in - het hoofdprogramma alleen maar aanroepen doet naar funkties - of procedures. Oh ja, natuurlijk niet maar een procedure - waarin het hele hoofdprogramma gecopieerd wordt (dan heeft - het oefenen nog geen nut). Oefen trouwens ook lekker veel - met het verschil tussen parameter en value parameters. - - Groetjes, - - Jeroen := Function( Smael ) diff --git a/Future Disk/34/Advanced Basic 4.md b/Future Disk/34/Advanced Basic 4.md deleted file mode 100644 index 8216684..0000000 --- a/Future Disk/34/Advanced Basic 4.md +++ /dev/null @@ -1,150 +0,0 @@ -Jaja, we gaan weer verder met de cursi... - ADVANCED BASIC CURSUS 4 - - - Welkom bij het vierde deel van deze cursus. In het eerste - deel van deze cursus zei ik dat er ongeveer 4 delen zouden - zijn, maar dat is niet zo. Na dit deel komen er nog twee - delen, eentje over data-verplaatsingen en eentje over - hybride programmeren met Advanced BASIC. - - - KARAKTERS - - In normaal BASIC is het niet mogelijk om makkelijk een - nieuwe karakter te maken. Advanced BASIC heeft hier een - speciaal commando voor, namelijk _CHAR. Het eerste parameter - geeft het karakter aan dat verandert moet worden en de - volgende 8 parameters geven de vorm van het karakter aan. - Een voorbeeld: - - 10 SCREEN 0:WIDTH 80 - 20 _CHAR(65,128,64,32,16,8,4,2,1) - 30 PRINT STRING$(80,65) - RUN - - Dit programmaatje verandert de letter 'A' (ascii-code is 65). - - - SNELLE COPY - - Advanced BASIC heeft een commando om snel een stuk van het - scherm te kunnen copi�ren, namelijk: - _COPY(sx,sy,sp,nx,ny,dx,dy,dp,[log_op]) - - De parameters sx en sy geven de x- en y-co�rdinaten weer - vanaf waar er gecopi�erd moet worden, sp is de bronpagina, - nx en ny geven aan hoeveel pixels er gecopi�erd moeten - worden, dx en dy zijn de bestemmingsco�rdinaten en dp is de - bestemmingspagina. Het parameter log_op geeft de logische - operatie aan, maar deze mag worden weggelaten. Een - voorbeeld: - - 10 SCREEN 5 - 20 CIRCLE (50,50),50,15 - 30 COPY (0,0,0,100,100,110,110,0) - 40 A$=INPUT$(1) - RUN - - Dit programaatje tekent een cirkel en copi�ert het naar - (110,110). - - Als je logische operatoren wilt gebruiken, moet je dat - anders doen dan in gewoon BASIC. Bij Advanced BASIC moet je - namelijk getallen gebruiken. Hier komt een lijstje welk - getal welk effect heeft: - - Getal Logical operatie - 0 - - 1 AND - 2 OR - 3 XOR - 4 NOT - 8 TIMP - 9 TAND - 10 TOR - 11 TXOR - 12 TNOT - - - MEER LIJNEN - - Een MSX2 (en hoger) kan 26,5 lijnen op scherm 0 en 1 laten - zien, maar MSX-BASIC gebruikt dit niet. Met Advanced BASIC - it het mogelijk om meer lijnen te gebruiken met het commando - _LINES(x). Het aantal lijnen kan alleen 24 en 26 zijn. - Jammer genoeg werkt de BASIC-editor niet goed in de laatste - lijnen. Hier is een voorbeeld: - - 10 SCREEN 0:_LINES(26):KEY OFF - 20 FOR A=0 TO 25 - 30 PRINT "Yippie, 26 lijnen op het scherm!" - 40 NEXT A - RUN - - Het resultaat is 26 keer de tekst van regel 30 op het - scherm. - - - LIJNTJES BEWERKEN - - Advanced BASIC heeft een aantal commando's om lijnen te - verwijderen, toevoegen en een gedeelte van een lijn te - wissen. Lijnen tussenvoegen kan met _INSLINE(y). Y geeft aan - op welke regel een nieuwe lijn moet komen. De lijnen eronder - zullen ��n regel omlaag scrollen en een lege lijn komt op - het scherm. Een voorbeeld: - - 10 SCREEN 0 - 20 PRINT "Dit is een tekstje" - 30 FOR A=0 TO 23 - 40 _INSLINE(0) - 50 NEXT A - RUN - - Dit programma heeft als resultaat een tekstje dat omlaag - scrollt (scrolled?). - - Met _DELLINE(y) is het mogelijk om een lijn te wissen. De - lijnen onder lijn y zullen omlaag scrollen. Met - _DELREST(x,y) is het mogelijk om een deel van een lijn te - wissen, en wel vanaf positie x,y. Een voorbeeld: - - 10 SCREEN 0 - 20 PRINT "Dit is een verdwijnende tekst" - 30 FOR A=31 TO 0 STEP -1 - 40 _DELREST(A,0) - 50 NEXT - RUN - - Het resultaat is een lijn dat letter voor letter verdwijnt. - - - HET RESTJE - - Het is mogelijk om met Advanced BASIC het scherm aan of uit - te zetten. Dit is ook mogelijk onder gewoon BASIC, maar met - Advanced BASIC is het toch eventjes iets makkelijker. _SCRON - zet het scherm aan en _SCROFF zet het scherm uit. - - Als je iets in een window print en het past er niet meer in, - dan scrollt de inhoud van het window omhoog. Dit zal echter - niet altijd gewenst zijn. Daarom is er een commando _SCROLLOFF - dat het scrollen uitzet. Natuurlijk is er dan ook een commando - dat het scrollen weer aan zet, en dat is _SCROLLON. - - Op een Turbo-R is het mogelijk om van processor te wissen. - Dit kan gedaan worden met _SPEED(x). Hier is een lijstje met - mogelijkheden: - - 0 = Z80 - 1 = R800 ROM - 2 = R800 DRAM - anders = fout - - _SPEED werkt ook op een MSX2(+), maar dan kan je alleen de - Z80-mode gebruiken. - - Nou, dit was het dan voor deze keer! - -Arjan Bakker diff --git a/Future Disk/34/Assembly cursus 3.md b/Future Disk/34/Assembly cursus 3.md deleted file mode 100644 index 095ba97..0000000 --- a/Future Disk/34/Assembly cursus 3.md +++ /dev/null @@ -1,186 +0,0 @@ -De assembly cursus gaat verder... - ASSEMBLY DEEL 3 - - - Welkom, welkom. Welkom bij het derde deel van deze cursus - assembly. Dit maal komen er 2 routine's aan bod, namelijk - een 8bits maal 16bits routine en een snelle copy routine om - het beeld snel op te bouwen. - - - VERMENIGVULDIGEN - - JW schreef op FD 31 dat hij een uur nodig had om een 8bits - maal 16bits routine te perfectioneren. Da's niet echt nodig, - je moet gewoon een 16bits routine pakken en je sloopt er wat - commando's uit en het werkt. - - - DE ROUTINE - - ; 8bits maal 16bits - ; In: A, DE: te vermenigvuldigen waarden - ; Uit: HL: resultaat - - MULUW: LD HL,0 - - MULUW1: RRA - JR NC,MULUW2 - ADD HL,DE - MULUW2: OR A - RET Z - SLA E - RL D - JP MULUW1 - - - UITLEG - - Ok�, de uitleg stond al op FD 30, dus komt 'ie hier niet - meer, op de veranderingen na natuurlijk. Allereerst de - registers. De accu en DE zijn het makkelijkst om te - gebruiken als input. De accu omdat je daarin snel waardes - kunt laden en DE omdat in HL het resultaat komt en het - handig is om BC te kunnen gebruiken als lusteller zonder de - stack te gebruiken. De 16bits optelinstructie ADD werkt - alleen met HL, dus moet het resultaat wel in HL komen. - - Toch even een korte uitleg. RRA schuift A 1 bit naar rechts. - Als carry gezet is, moet DE bij HL opgeteld worden. Dan - wordt er gecontroleerd of A al 0 is. Als dat zo is, is de - routine klaar. Is dat niet zo, dan wordt DE met 2 - vermenigvuldigt en begint de routine overnieuw. - - Als je de routine niet snapt, lees dan FD 30 even en als het - goed is snap je het dan wel (anders ben je een domme aap). - - - SNELLE COPY ROUTINE - - Stel, je wilt snel een screen 5 scherm opbouwen. Da's niet - moeilijk. Stel, je routine is te traag. Dat kan gebeuren. - Dan is hier de oplossing voor je probleem, namelijk een - snelle copy-routine. - - Laten we voor het gemak ervan uitgaan dat je patterns van - 8*8 gebruikt en dat je voor elke pattern 1 byte gebruikt. - Omdat er maar 32 tekens op ��n rij kunnen, heb je maar 5 - bits nodig om aan te geven welk teken van een rij je nodig - hebt. Er blijven dan 3 bits over die aangeven welke rij je - gebruikt. Je kunt de X-positie dan uitrekenen met: - - AND 31 - ADD A,A ; Met 8 vermenigvuldigen - ADD A,A ; (32*8=255) - ADD A,A - - En de Y-positie kun je uitrekenen met: - - AND 224 - SRL A ; Door 4 delen (32/4=8) - SRL A - - Het omrekenen van een byte naar coordinaten gaat dus als - volgt: - - MOVPAT: LD A,(HL) ; Lees byte - - AND 31 ; 32 patterns per rij. - ADD A,A ; Bereken X - ADD A,A - ADD A,A ; A = A * 8 - - LD (SX),A ; Sla X op - - LD A,(HL) ; Lees byte weer - - AND 224 ; 8 rijen - RRA ; Bereken Y - RRA ; Door 4 delen - - LD (SY),A ; Sla Y op - - Vervolgens moet de pattern geprint worden. - - PUSH HL - CALL WAITVDP ; Wacht op VDP - CALL COPY ; Kopi�er pattern - POP HL - - LD A,(DX) ; Pas bestemming X aan - ADD A,8 - LD (DX),A - - JR NZ,MOVPAT1 - - LD A,(DY) ; Pas bestemming Y aan - ADD A,8 - LD (DY),A - - MOVPAT1: - INC HL ; Pas pointer aan - - Zo, da's heel wat. Deze routine past ook automatisch de - pointer naar de screendata aan en ook de bestemmings- - co�rdinaten worden aangepast. Bouw er een lusje omheen en je - scherm wordt snel opgebouwd. Gebruik eventueel geen CALL - WAITVDP en CALL COPY, maar prop die routine's gewoon in deze - routine. Voor de zekerheid komen hier nog even de routines - WAITVDP en COPY. - - - WAT EXTRA ROUTINES - - WAITVDP: ; Wacht totdat VDP klaar is - LD A,2 - OUT (#99),A - LD A,#8F - OUT (#99),A - IN A,(#99) - EX AF,AF - XOR A - OUT (#99),A - LD A,128+15 - OUT (#99),A - EX AF,AF - RRA - JR C,WAITVDP - RET - - COPY: LD A,32 ; Register 32 - OUT (#99),A - LD A,17+128 ; Auto-increment - OUT (#99),A - LD C,#9B - LD B,15 - LD HL,SX - OTIR ; Pomp bytes naar - RET ; register - - SX: DEFB 0,0 - SY: DEFB 0 - P1: DEFB 0 - DX: DEFB 0,0 - DY: DEFB 0 - P2: DEFB 0 - NX: DEFB 8,0 - NY: DEFB 8,0 - REST: DEFB 0,0 - COMMAN: DEFB #D0 - - - TOT SLOT - - Eventueel kun je in plaats van ��n OTIR 15 OUTI's gebruiken, - want dat is weer ietsje sneller. LD B,15 kan dan komen te - vervallen. Verder geldt: Hoe groter de patterns, des te - sneller de routine. - - Als je nog idee�n hebt voor een onderwerp, stuur het dan op - naar de FD en misschien komt er dan wel een tekstje over dat - onderwerp. - - De sources staan ook op disk onder de naam MULUW.ASM en - SCRCOPY.ASM. - -Arjan Bakker diff --git a/Future Disk/34/Pascal 5.md b/Future Disk/34/Pascal 5.md deleted file mode 100644 index 95d07d1..0000000 --- a/Future Disk/34/Pascal 5.md +++ /dev/null @@ -1,333 +0,0 @@ -Hier volgt alweer deel 5 van mijn PASCAL cursus. Ik hoop dat mensen het leuk vinden dat ik dit doe, anders kan ik beter ophouden. - PASCAL 5 - ======== - - - ���� Alweer deel 5 van deze cursus! Wat gaat de tijd toch - ���� snel(NvdR: snif). Deze keer een kleine cursus, omdat het - ���� over een gemakkelijk onderwerp handelt. Deze cursus - ���� behandelt namelijk het maken van eigen types. - - Bij het declareren van een variabele konden we tot nog toe - alleen maar kiezen uit de standaard type's (integer, real, - boolean, etc.). In PASCAL is het echter ook mogelijk om je - eigen type's te maken en wel als volgt: - - TYPE - OpsomType = {Item1,Item2,Item3}; - SubrangeType = 1..10; - ArrayType = ARRAY[1..10] OF AnderType; - - Je kunt dus een opsommingstype maken bijvoorbeeld: - - DagenVanDeWeek = {Maandag,Dindag,Woensdag,Donderdag,Vrijdag, - Zaterdag,Zondag} - - Of een subrangetype (van elk ander type). Bijvoorbeeld: - - DagenVanDeMaand = 1..31 (* integers dus *) - - Of een ARRAY type. Bijvoorbeeld: - - WekenVanEenJaar = ARRAY[1..52] OF DagenVanDeWeek - - Vervolgens kun je de types gebruiken, maar let wel goed op met - toekenningen e.d. Neem bijvoorbeeld het volgende: - - VAR - Dag : DagenVanDeWeek; - - Dan mag - - Dag := Maandag; - - Maar niet - - Write("Geef dag : "); - Readln(Dag); - - De type's verschillen immers. Bij Readln lees je een integer, - real of string, maar niet een DagenVanDeWeek. - - Wat ook niet kan is - - Dag := Maandag; - Writeln("Het is vandaag ",Dag); - - En wel om dezelde reden als bij Readln. Wat wel kan is - - Dag := Maandag; - CASE Dag OF - Maandag : Write("Maandag"); - Dinsdag : write("Dinsdag"); - . - . - . - - Experimenteer maar eens een beetje met het cre�ren van eigen - type's en je zult zien dat dit heel handig kan zijn. - - Een functie die een beetje met deze type declaratie te maken - heeft is de IN functie. Deze werkt als volgt: - - IF Dag IN {Maandag,Dinsdag,Woensdag,Donderdag,Vrijdag} THEN - writeln("Dit is een werkdag"); - - Je kunt dus met IN kijken of de waarde van een variabele in - een gegeven verzameling zit. Die verzameling moet je wel eerst - opsommen, maar dat is een kleine prijs om te betalen tegenover - (in dit geval) 5 IF statements. - - Zo, dit was kort maar krachtig(NvdR: tja). - - Jeroen "Ik beloof beterschap" Smael - En de Pascal cursus gaat verder... - PASCAL 6 - ======== - - - ���� Tja, vorige keer was ik er niet helemaal met mijn koppie - ���� bij, want ik heb een deel van wat ik moest vertellen - ���� vergeten(NvdR: de eikel!). Ik heb verteld dat je eigen - ���� types kunt maken, maar ��n van de belangrijkste types ben - ik vergeten. Ik ben namelijk het RECORD en de string - vergeten. Hierbij dan ook mijn excuses en de aanvullende - informatie. - - - TYPE - - Over de string kan ik heel snel zijn. De string is een "PACKED - ARRAY[1..?] of char". Een PACKED ARRAY is een array waarvan de - lengte intern wordt bijgehouden. Iets wat bij een string - noodzakelijk is... - - PROGRAM StringVoorbeeld; - - TYPE - Woord = PACKED ARRAY[1..10] OF char; - - VAR - A : Woord; - B : Woord; - - BEGIN (* StringVoorbeeld *) - A:='hallo'; - B:=A; - Writeln(A); - Writeln(B); - END. (* StringVoorbeeld *) - - Het bovenstaande programma lijkt goed (A:=B mag bij arrays, - zolang de arrays van het zelfde type en even groot zijn), maar - er zal twee keer het woord 'hallo' verschijnen, met daarachter - 5 ongewilde karakters (mocht het zo zijn dat het programma - niet al een foutmelding geeft bij de opdracht A:='hallo', - omdat dat niet voldoet aan de voorwaarde van dezelfde grootte). - Bij een PACKED ARRAY zoekt de computer zelf uit hoe groot het - ARRAY is en lost alle genoemde problemen dus op. Bij een - aantal compilers is het mogelijk om een type te gebruiken dat - "string" heet. Genoemd type wordt gebruikt bij TYPE met - "woord = string[10]" of bij VAR met "A : string[10]". - - Dat ik RECORD's vergeten ben is veel erger, omdat daar nou - juist de meeste leuke dingen mee gedaan kunnen worden. Een - klein voorbeeldje: - - - PROGRAM RecordVoorbeeld; - - TYPE - datum = RECORD - dag : 1..31; - maand : 1..12; - jaar : 0..5000; - END; - persoonsgegevens = RECORD - naam : string[30]; (* ik maak - gebruik van - het string - type *) - geboortedatum : datum; - END; - - VAR - persoon : persoonsgegevens; - - BEGIN (* RecordVoorbeeld *) - persoon.naam:='Jeroen Smael'; - persoon.geboortedatum.dag:=27; - persoon.geboortedatum.maand:=10; - persoon.geboortedatum.jaar:=1970; - END. (* RecordVoorbeeld *) - - - Op deze manier kun je dus hele "gegevensbomen" aanleggen. Bij - de persoonsgegevens kun je ook nog het adres, de geboortestad, - etc., etc. toevoegen. Alles wat je maar wilt. Zoals je ziet - moet je wel, om bij de velden te komen een punt gebruiken. - Deze punt is vergelijkbaar met de \ van DOS (het scheidings- - teken van subdirectory's). Tevens zie je dat ik pas jarig ben - geweest, maar dat terzijde(NvdR: inderdaad, dat boeit ons, - ja). - - Met genoemde velden zijn verder natuurlijk wel alle - bewerkingen mogelijk, zo zou de opdracht: - "persoon.geboortejaar:=persoon.geboortejaar+1" een geldige - opdracht zijn. - - Een hele bruikbare "opdracht" bij records is de CASE opdracht. - Deze maakt het mogelijk om ��n of meerdere veldnamen weg te - laten. Met gebruikmaking van de CASE opdracht zou het vorige - (hoofd)programma er als volgt hebben uitgezien: - - BEGIN (* RecordVoorbeeld *) - CASE Persoon OF - naam:='Jeroen Smael'; - geboortedatum.dag:=27; - geboortedatum.maand:=10; - geboortedatum.jaar:=1970; - END; - END. (* RecordVoorbeeld *) - - Hetzelfde (de CASE) kunnen we natuurlijk ook toepassen bij de - geboortedatum en dan ziet het (hoofd)programma er als volgt - uit: - - BEGIN (* RecordVoorbeeld *) - CASE Persoon OF - naam:='Jeroen Smael'; - CASE geboortedatum OF - dag:=27; - maand:=10; - jaar:=1970; - END; - END; - END. (* RecordVoorbeeld *) - - Zoals te zien spaart dit een heleboel tikken. Let er - natuurlijk wel op dat de CASE afgesloten wordt door een END - (anders krijg je een compiler fout). - - - Files - - Het zou uiteraard ook leuk zijn als we met PASCAL toegang - zouden hebben tot de diskette. Gelukkig hebben de makers - daaraan gedacht en kan dat. Voor de beeldvorming zal ik - uitleggen hoe PASCAL een file "ziet". - - Een file is in PASCAL een lange keten gegevens. De gegevens - zitten (en zullen ten eeuwige dagen blijven zitten) in de - volgorde waarin ze zijn weggeschreven. Bij het werken met een - file schuift er een "window" over de file, waardoor altijd - maar ��n gegeven per keer "zichtbaar" is. Het genoemde window - heeft trouwens de onprettige eigenschap dat het alleen maar - vooruit kan schuiven. Ophalen en wegschrijven van waardes - gebeurt via het window. Het window is te bereiken met "File^" - (waar File de naam van de filevariabele is). Ik zal nu wat - opdrachten bespreken die mogelijk zijn met files, waarna nog - een voorbeeld programma volgt. Opdrachten zijn: - - RESET(File) - Opent een file zodat er in gelezen kan worden (zet het - window aan het begin van de file). - REWRITE(File) - Opent de file en maakt hem geschikt om in te schrijven - (file is nu leeg, ook al was hij dat niet!!). - GET(File) - Schuift het window een plaats op (de nieuwe waarde kan met - "Waarde:=File^" opgevraagd worden). - PUT(File) - Zet de waarde van het window in de file en schuift het - window een plaats op (de window waarde kan veranderd worden - met "File^:=Waarde"). - READ(File,Waarde) - Leest uit de file en plaats de gelezen waarde in "Waarde" - (geen geklooi meer met het window, hier gebeurt dat - allemaal automatisch). - READLN(File,Waarde) - Idem als READ, maar leest tevens tot het einde van de regel - (wordt gebruikt bij tekstfiles). - WRITE(File,Waarde) - Schrijft de waarde van "Waarde" in de file en schuift het - window door (ook hier geen geklooi meer met het window). - WRITELN(File,Waarde) - Idem als WRITE, maar plaatst tevens een EOLN (End OF LiNe) - teken in de file (wederom bij tekstfiles). - EOF(File) - Geeft de waarde TRUE als het einde van de file bereikt is - (EOF = End Of File). - EOLN(File) - Geeft de waarde TRUE als het einde van de regel bereikt is - (EOLN = End Of LiNe). - - Offici�el zijn genoemde opdrachten alle opdrachten voor files, - maar de meeste compilers hebben nog twee extra opdrachten, en - dat zijn: - - ASSIGN(File,"FileNaam") - Dit koppelt de "File" aan de "FileNaam". M.a.w. Als ik iets - in de file schrijf, dan komt dit op de schijf in de file - "FileNaam" te staan. Volgens de regels van PASCAL is dit - niet nodig, omdat de fysieke file (de file op schijf) - dezelfde naam krijgt als de variabele "File" heeft. Veel - compilers hebben echter een ASSIGN opdracht nodig, anders - gebeurt er niets (vaak niet eens een foutmelding en al - helemaal geen file). - CLOSE(File) - Dit moge wel duidelijk zijn. Hier wordt de file gesloten. - Deze opdracht zorgt ervoor dat de file ook voor DOS - gesloten wordt, zodat er niet een ge-opende file achter- - blijft als het programma stopt. Deze opdracht moet dus - alleen op het einde van het programma staan. Ook deze - opdracht is geen standaard, maar moet ook bij de meeste - compilers worden toegevoegd voor een goede werking. - - Zo, en dan nu een voorbeeldje: - - PROGRAM FileVoorbeeld; - - TYPE - FileType = FILE OF integer; (* FILE OF AnyType is - mogelijk *) - - VAR - FileVar : FileType; - Teller : integer; - - BEGIN (* FileVoorbeeld *) - ASSIGN(FileVar,"testfile.dat"); (* voor de zekerheid *) - REWRITE(FileVar); (* ik wil er iets - inschrijven *) - FOR Teller:=1 TO 5000 DO - Write(FileVar,Teller); (* dat doe ik hier *) - FOR Teller:=5000 DOWNTO 1 DO - Write(FileVar,Teller); (* en hier ook *) - RESET(FileVar); (* nu wil ik lezen uit - de file *) - WHILE NOT EOF(FileVar) DO - BEGIN - Read(FileVar,Teller); (* hier noem ik - expliciet de file *) - Write(Teller); (* hier niet, dus gaat - de output naar het - standaard uitvoerap- - paraat en dat is het - beeldscherm *) - END; - CLOSE(FileVar); (* voor de zekerheid *) - END. (* FileVoorbeeld *) - - Dit voorbeeld zou een heleboel duidelijk moeten maken. Alles - wat je nu nog moet doen is verder experimenteren. Probeer eens - een tekstfile te lezen en/of schrijven, dan kun je zien wat - EOLN precies doet. - De opdrachten GET en PUT worden weinig gebruikt, maar je kunt - eens kijken hoe ze precies werken (goed voor de beeldvorming). - - Zo, dat was het dan alweer voor deze keer. Groetjes van, - - Jeroen 'ik ben nog lang niet aan mijn EOF' Smael - - C YA @!! diff --git a/Future Disk/35/Assembly cursus 4.md b/Future Disk/35/Assembly cursus 4.md deleted file mode 100644 index 21682d6..0000000 --- a/Future Disk/35/Assembly cursus 4.md +++ /dev/null @@ -1,165 +0,0 @@ -De assembly cursus gaat verder... - ASSEMBLY (4) - - ���� - ���� - ���� - ���� - - - Het schiet eindelijk een beetje op met deze cursus, maar ja, - deze cursus is ook maar een kwestie van inspiratie. Voor - deze keer heb ik wat routines in elkaar geknutseld om de 2 - extra kleuren van de MSX 2 in screen 0 te kunnen gebruiken. - Ik ga niet vertellen hoe je ze aan moet zetten enzo, want - dat is een kwestie van wat VDP-registertjes vullen. Nee, - deze tekst gaat over hoe snel de kleuren op een bepaalde - positie te zetten of weg te halen. - - Normaal gesproken begint de tabel op adres 2048 in het VRAM. - Deze tabel is 240 bytes groot (=24*80 bits), tenzij je het - aantal lijnen op 26,5 zet, want dan is deze tabel 270 bytes - groot. Vergeet dan ook niet om deze tabel te verplaatsen als - je meer dan 24 regels gebruikt, want de schermtabel - overschrijft dan de kleur-tabel (de schermtabel is dan 2160 - bytes groot). - - Maar goed, ��n byte van de kleurtabel geeft voor 8 plaatsen - aan of ze aan (1) of uit (0) staan. Adres 2048 geeft dus van - coordinaten (0,0) tot (7,0) aan of ze aan of uit staan, - adres 2049 van (8,0) tot (15,0) enz. Een regel gebruikt dan - 10 bytes (=80 bits). Het adres van een coordinaat kun je dan - uitrekenen door de y-coordinaat met 10 te vermenigvuldigen, - de x-coordinaat door 8 te delen, deze 2 optellen en bij 2048 - (het startadres van de tabel) op te tellen. De volgende - routine doet dat: - - ; Bereken adres in kleurtabel - ; In: D: x-coordinaat - : E: y-coordinaat - ; Uit: HL: adres in kleurtabel - - CALCAD: LD HL,2048 ; Start kleurtabel - - LD A,D ; Deel X door 8 - SRL A - SRL A - SRL A - CALL HLA ; en tel bij HL op - - LD A,E ; Vermenigvuldig Y met 10 - ADD A,A - LD B,A - ADD A,A - ADD A,A - ADD A,B - CALL HLA ; en tel bij HL op - RET ; Einde - - De routine HLA doet niets anders dan HL en A bijelkaar op te - tellen en maakt alleen gebruik van de registers A en HL. - Deze routine ziet er als volgt uit: - - HLA: ADD A,L - LD L,A - RET NC - INC H - RET - - Nu kunnen we het adres berekenen van een karakter. Nu moeten - we nog het bitnummer berekenen. De volgende routine doet - dat: - - CALCBT: LD A,D ; Laad x-coordinaat - AND 7 ; laagste 3 bits - LD B,A ; aantal keren schuiven - LD A,128 ; eerste positie is 128 - RET Z ; Positie = 0? Ja -> klaar! - DIVIDE: RRA ; Deel positie door 2 - DJNZ DIVIDE ; Herhalen - RET - - Nu hebben we het bitmasker om een karakter aan te zetten. - Als je een karakter uit wilt zetten, moet je dit masker - inverteren (XOR 255). We kunnen voorts een routine schrijven - die karakters aan en uitzet. Hier komen ze: - - WRTVDP: EQU #47 - WRTVRM: EQU #0177 - RDVRM: EQU #0174 - BIGFIL: EQU #016B - - ; CLS-routine - CLS: LD HL,2048 - LD BC,240 - LD A,0 - JP BIGFIL - - ; Print-routine - ; In: D: X-coordinaat - ; E: Y-coordinaat - ; B: aantal - PUT: PUSH BC - - CALL CALCAD ; Bereken adres - - CALL RDVRM ; Lees oude byte - LD C,A ; Opslaan in C - - CALL CALCBT ; Bereken bitmasker - - OR C ; Originele byte eroverheen - CALL WRTVRM ; Wegschrijven - - INC D ; Pas X aan - LD A,D - CP 80 ; Laatste positie? - JP C,PUT1 ; Nee -> Y niet aanpassen - - LD D,0 ; Pas X en Y aan - INC E - - PUT1: POP BC - DJNZ PUT ; Herhaal routine - RET - - ; Verwijder alternatieve kleuren - ; In: D: X-coordinaat - ; E: Y-coordinaat - ; B: aantal - UNPUT: PUSH BC - - CALL CALCAD ; Bereken adres - - CALL RDVRM ; Lees byte - LD C,A ; Sla het op - - CALL CALCBT ; Bereken bitmasker - - CPL ; Inverteer het - AND C ; Originele masker erover - CALL WRTVRM ; Schrijf byte weg - - INC D ; Pas X aan - LD A,D - CP 80 ; Laatste positie? - JP C,UNPUT1 ; Nee -> Y niet aanpassen - - LD D,0 ; Pas X en Y aan - INC E - - UNPUT1: POP BC - DJNZ UNPUT ; Herhaal routine - RET - - - Deze routines kunnen natuurlijk nog wat aanpassingen - gebruiken, zoals de routines CALCBT en CALCAD direct in de - code te gebruiken, maar voor een cursus moet dat juist niet - omdat het dan een beetje onoverzichtelijker wordt. De - routines zelf spreken voor zich, want er staat genoeg - commentaar bij. Oh ja, de routines staan ook op diskette en - wel in de file ALTCOL.ASM. Tot een volgende keer! - - -Vincent diff --git a/Future Disk/35/Copy in BASIC.md b/Future Disk/35/Copy in BASIC.md deleted file mode 100644 index d970a8b..0000000 --- a/Future Disk/35/Copy in BASIC.md +++ /dev/null @@ -1,82 +0,0 @@ -Het copy commando in Basic..hmm interessant...hmm ja, daar heb ik nu altijd al eens wat over willen weten...aja, ja ja, ahum, mmmm, ja ja ja interessant...aha hmm ye ye yep ja ja - COPY IN BASIC - - ���� - ���� - ���� - ���� - - - Het COPY-commando heeft meerdere betekenissen. Je kunt er - bestanden mee copi�ren en stukjes van een beeld mee copi�ren. - Dat laatste kan op twee manieren, namelijk van VRAM naar - VRAM en van VRAM naar een array of andersom. De eerste - functie kent iedereen natuurlijk wel, maar de tweede is toch - wel onbekend. Zoals gezegd kun je dus ook een array - gebruiken om naar te copi�ren of weer in het VRAM te zetten. - - Voordat je een stuk scherm naar een array copi�ert, moet je - die eerst berekenen en defini�ren. De grootte van een array - kan met het volgende programmaatje berekend worden: - - 10 PRINT "Bereken grootte voor array-dimensie voor - copy-commando" - 20 PRINT:INPUT "Linker X-coordinaat";X1 - 30 INPUT "Boven y-coordinaat";Y1 - 40 INPUT "Rechter X-coordinaat";X2 - 50 INPUT "Onder y-coordinaat";Y2 - 60 PRINT:INPUT "Schermnummer";S - 70 PRINT:INPUT "Variabele type (% = Integer, ! = Single - precision en # = Double precision";A$ - 80 D=4:IF S=6 THEN D=2 - 90 D=INT((D*(ABS(X2-X1)+1)*(ABS(Y2-Y1)+1)+7)\8)+4 - 100 T=2:IF A$="!" THEN T=4 ELSE IF A$="#" THEN T=8 - 110 D=INT(D/T) - 120 PRINT:PRINT "DIM M(";MID$(STR$(D),2);")" - - Zo, nu komt de COPY-commando zelf aan bod. Eerst de - COPY-commando om een deel van het beeld in het geheugen te - zetten. - - COPY (X1,Y1)-(X2,Y2)[,P] TO V - - X1 is de linker-coordinaat van het te copi�ren gedeelte. Y1 - is de boven-coordinaat van het te copi�ren gedeelte. X2 is - de rechter-coordinaat van het te copi�ren gedeelte. Y2 is de - onder-coordinaat van het te copi�ren gedeelte. P is de - pagina-nummer. V is de naam van de variable waar de tekening - in gezet moet worden. Alleen P hoeft niet ingevuld worden, - zoals te zien is aan de vierkante haken. - - Okee, de tekening moet natuurlijk ook weer op het beeld - kunnen komen. Dit doen we met: - - COPY V[,S] TO (X,Y)[,P[,O]] - - V is weer de naam van de variable waar de tekening in zit. S - is de soort bewerking wat er met de tekening moet gebeuren. - Hierbij is 0 normaal, 1 = horizontaal spiegelen, 2 = - verticaal spiegelen, 3 = 1 + 2. X en Y zijn de coordinaten - waar de tekening heen moet. P is weer de paginanummer en O - is de logische operatie. Aangezien deze tekst niet over - logische operaties gaat, ga ik daar dus ook niet verder op - in. S, P en O mogen weggelaten worden. Hier komt een - voorbeeldprogrammaatje. Start het op en je ziet het effect. - - 10 SCREEN5:DIM M(66):LINE (0,0)-(0,15),15 - 20 LINE (0,7)-(15,7),15 - 30 COPY (0,0)-(15,15) TO M - 40 COPY M,0 TO (100,50) - 50 COPY M,1 TO (100+15,80) - 60 COPY M,2 TO (100,110+15) - 70 COPY M,3 TO (100+15,150) - 80 A$=INPUT$(1) - - Zoals je ziet kun je dus makkelijk effecten gebruiken in - BASIC, maar je moet natuurlijk wel zorgen dat het wel in het - geheugen past, want naar een array copi�ren kost al snel - veel geheugen. Tot de volgende keer... - - -Vincent - diff --git a/Future Disk/35/Pascal 7.md b/Future Disk/35/Pascal 7.md deleted file mode 100644 index 85739e9..0000000 --- a/Future Disk/35/Pascal 7.md +++ /dev/null @@ -1,146 +0,0 @@ -Jeroenie gaat verder met de Pascal cursus... - PASCAL (7) - - - ���� We zijn bijna aan het einde gekomen van een reeks PASCAL - ���� cursi. Er zijn nog maar twee onderwerpen die ik wil - ���� behandelen: POINTERS en RECURSIE. Pointers is een soort - ���� data-type in PASCAL en recursie is een soort - programmeermethode. Omdat beide onderwerpen interessant - en (mijns inziens) belangrijk voor een programmeur zijn - besteed ik per onderwerp twee teksten hieraan (zodoende kan - ik dus nog drie teksten en FD nummers vooruit). Ik begin dus - met pointers (les 1). - - Wat is het voordeel van een FILE ten opzichte van een ARRAY: - - oneindig (een file kan in principe oneindig lang zijn) - - flexibele grootte (een file kan altijd langer of korter - gemaakt worden) - - weinig geheugen nodig (voor een file is bijna geen - geheugenruimte nodig, wel schijfruimte natuurlijk, maar - daar hebben we tegenwoordig genoeg van) - - Wat is het voordeel van een ARRAY ten opzichte van een FILE: - - snel(1) (ieder element kan onafhankelijk van de andere - opgevraagd worden, dus niet eerst de hele file de revue - laten passeren voordat het laatste element gebruikt kan - worden) -- snel(2) (alles staat in het geheugen en geheugen is v��l - sneller dan disk) -- gemakkelijk (makkelijk te programmeren, denk maar eens aan - een sorteer-algoritme voor files) - - Door genoemde voordelen te combineren zou men een super - gemakkelijk en snel data-type moeten kunnen krijgen. Men heeft - lang (eigenlijk niet, maar voor het verhaal staat dat wel - leuk) gedacht en is met pointers gekomen. Het had snel en - gemakkelijk moeten zijn. Het is snel, maar zeker NIET - gemakkelijk. Wat zijn pointers dan wel vraag je je af? - - snel (alles staat in het geheugen) - - oneindig (zolang er geheugen is kunnen er pointers - aangemaakt worden) -- flexibele grootte (tijdens programma executie kunnen nieuwe - pointers aangemaakt worden) - - Je kunt je nu natuurlijk nog niets bij pointers voorstellen, - maar dat ga ik even veranderen. Wat is een pointer namelijk in - de computer (hoe werkt het)? Een pointer is (zoals de naam al - zegt) een wijzer (NvdR: grote meid!). Genoemde wijzer kan - wijzen naar niets of naar een data-element. Wijst het naar - niets, dan wijst hij naar NIL (gereserveerd woord), dat - (waarschijnlijk) het getal 0 is en dus geheugenruimte 0 is. - Wijst het naar een data-element dan is de pointer het adres - waar dat data-element gevonden kan worden. Dus als ik een - pointer A heb, dan kan de inhoud van A NIL zijn of - (bijvoorbeeld) #a084. NIL wil zeggen dat de pointer nergens - naar wijst, en #a084 dat de pointer naar adres #a084 wijst. - Staat op adres #a084 het getal 10, dan wijst de pointer dus - het getal 10 aan. Grafisch wordt een en ander vaak als volgt - weergegeven: - - A - +-+ +----+ - | |--->| 10 | - +-+ +----+ - - Bovenstaand geval is als een pointer een byte (1 byte in het - geheugen) aanwijst. Er zijn dus wel 3 bytes nodig om een en - ander goed te laten werken (2 voor de pointer (16 bits adres) - en 1 voor het data-element (byte)). Een pointer kan elk data- - type aanwijzen dat de gebruiker maakt, hierdoor is het - mogelijk om een zogenoemde gelinkte lijst te maken (een - pointer die naar een pointer wijst die naar een pointer wijst - die naar een pointer wijst die naar een pointer wijst die naar - een pointer wijst die naar een pointer wijst die naar een - pointer wijst die naar een pointer wijst die naar een pointer - wijst ...............). Op zich heb je daar dus niets aan, - maar als je alle pointers nu eens naar een RECORD laat wijzen - dat een data-element EN een pointer bevat, dan kom je al een - heel eind. Grafisch ziet dat er als volgt uit: - - Hoofd - +-+ +---+-+ +---+-+ +---+-+ +---+-+ +---+-----+ - | |--->| 5 | |--->| 9 | |--->| 4 | |--->| 0 | |--->| 1 | NIL | - +-+ +---+-+ +---+-+ +---+-+ +---+-+ +---+-----+ - - Allemaal heel leuk, maar hoe gebruik je dit (oftewel geef een - programma, dan zien we tenminste iets). Kijk maar eens naar de - file "PASCAL7.PAS" op deze diskette, daar staat een voorbeeld - in. - - Bij TYPE staat de declaratie van een pointer: - typenaam1 = ^typenaam2 (* ^ staat voor 'pointer naar' *) - - Hier is dus wel iets geks aan de hand, want Next is een - pointer naar Element, maar Element is nog niet bekent...... - MAG DAT???? Ja, dat mag, als uitzondering. Zouden we Element - en Point in de declaratie omdraaien, dan zouden we namelijk een - soortgelijk probleem hebben omdat in Element, Next van het - type Point is. Bij pointers mag er dus een type vooruit genoemd - worden. Overigens wel in de volgorde zoals in het voorbeeld - staat (dus eerst het pointer-type en daarna pas het type waar - de pointer naar wijst). - - De variabele declaratie zal geen problemen opleveren, dit in - tegenstelling tot het hoofdprogramma. Het eerste nieuwe dat we - tegenkomen is 'Main:=NIL'. Aangezien Main nog een - ongedefinieerde waarde heeft, maken we deze eerst gedefinieerd - (vanaf nu wijst Main dus nergens naar). Het volgende is - 'NEW(Temp)'. Hier wordt een geheugenplaats aangevraagd voor - het data-type van Temp. (voor de opdracht NEW wijst de pointer - Temp naar een ongedefinieerde plaats in het geheugen. Bij de - NEW opdracht wordt er in het geheugen gezocht naar een plaats - waar het data-type van de pointer inpast (in dit geval een - integer en een pointer)). Deze geheugenruimte wordt dan - gereserveerd voor zulk een data-type en de pointer wijst vanaf - nu naar genoemde plaats in het geheugen). - - De toekenningsopdrachten zijn min of meer vanzelfsprekend als - je weet dat pointer^ het data-element is (dus Main^ is een - RECORD met twee velden (Value en Next), de inhoud van Value - is dus te bereiken met Hoofd^.Value). Wel moet ik vermelden - dat als je een pointer (bijvoorbeeld Temp) zelf veranderd, dat - de computer dan niet de geheugenruimte vrijmaakt waar de - pointer naar wijst. Door alsmaar 'NEW(Temp)' als opdracht te - geven zou het geheugen dus vollopen (zorg ervoor dat je het - adres van het data-element ergens bewaart, anders ben je het - voorgoed KWIJT in het walhalla van je computer geheugen). In - het voorbeeld programma raak ik niets kwijt (ook visueel - zichtbaar) omdat ik een gelinkte lijst maak (ik laat de - elementen naar elkaar wijzen). - - Wil je de geheugenplaats waar een pointer naar wijst vrij - maken dan gebruik je DISPOSE (zoals ook op het einde van het - programma te zien is). - - Zo, dat was het dan alweer. Volgende keer meer, veel meer over - pointers, maar voor nu 2 opdrachten om jezelf te testen: - - (1) Zie voorbeeld programma, maar nu de getallen in volgorde - van invoer in de lijst plaatsen. - (2) Zie voorbeeld programma, maar nu de getallen gesorteerd in - de lijst plaatsen. - - Veel plezier, - -Red XIII diff --git a/Future Disk/35/Pascal 8.md b/Future Disk/35/Pascal 8.md deleted file mode 100644 index 2294813..0000000 --- a/Future Disk/35/Pascal 8.md +++ /dev/null @@ -1,381 +0,0 @@ -Jeroen programmeert verder en verder en kan het nog steeds niet... - PASCAL (8) - - - ���� Hallie hallo, hier is Smael weer met zijn PASCAL cursus. - ���� Deel 8 deze keer (nog twee en dan is het alweer - ���� voorbij). In deel 8 gaan we dieper in op pointers. - ���� Vorige keer heb ik uitgelegd wat pointers zijn en wat je - ermee kunt. Nu is het dus tijd voor een groot voorbeeld. - Als voorbeeld neem ik een programma om namen en adressen op te - slaan (een soort database dus). Goed, daar gaat 'ie (wat - hebben we weer een plezier)!! (NvdR: ja nou) - - Het programma staat op de disk als 'PASCAL8.PAS'. De listing - vind je terug in deze tekst, maar alleen ter verduidelijking. - - De declaraties veronderstel ik bekend (moet je kunnen) en daar - ga ik dus niet verder op in. Wel staan ze hier even vermeld, - zodat je de rest van het programma begrijpt: - - PROGRAM Pascal8 (Input,Output,Names); - - CONST - Max = 30; - - TYPE - Point = ^Row; - Row = RECORD - Name : String[Max]; - Address : String[Max]; - Next : Point; - END; - - VAR - Names : Text; - Choice : integer; - Main : Point; - Temp : Point; - Number : integer; - - Ik ga dus verder met de eerste procedure, aangezien hier - misschien dingen zijn die je niet begrijpt. Als ik zo naar - deze procedure kijk, dan kom ik tot de ontdekking dat je - alleen het commando 'ClrScr' niet kent, maar dat de naam alles - duidelijk maakt. Let ook op hoe ik het probleem van de - toetsdruk oplos. De computer wacht totdat ik op de - toets heb geramd, daarvoor kun je dus alle letters inrammen - die je wil (ze zullen zelfs zichtbaar zijn op het scherm). - Niet erg netjes dus, maar dat kun JIJ verbeteren (gebruik de - functie 'KeyPressed'). Verder gesneden koek: - - PROCEDURE welcome; - - BEGIN (* welcome *) - clrscr; - writeln('This is an example that comes with FD#35'); - writeln; - writeln('This little programm makes it possible'); - writeln('to create a list of addresses using'); - writeln('pointers.'); - writeln; - writeln; - writeln('Enjoy !!'); - writeln; - writeln; - writeln; - write('Press to continue.'); - readln; - END; (* welcome *) - - Ook deze procedure moet gesneden koek zijn (alleen maar wat - Writeln's en Readln's). Wederom kun je een en ander - verbeteren. Als je namelijk een verkeerde keuze maakt, dan - wordt op de volgende regel opnieuw naar je keuze gevraagd. - Maak je ongeveer 20 keer de verkeerde keuze, dan is het - keuzemenu niet meer te zien (uit het beeld geschoven) en dat - is niet zo netjes. Read it and weep : - - PROCEDURE menu(VAR choise:integer); - - BEGIN (* menu *) - clrscr; - writeln('You can choose from :'); - writeln; - writeln('(1) Load adresses'); - writeln('(2) Insert address'); - writeln('(3) Show adresses'); - writeln('(4) Delete address'); - writeln('(5) Save addresses'); - writeln('(6) Stop'); - writeln; - writeln; - writeln; - choise:=0; - REPEAT - write('Your choice : '); - readln(choise); - UNTIL (choise>=1) AND (choise<=6); - END; (* menu *) - - Hier wordt het interessant. Er wordt een file ingelezen van - namen die ooit al eens zijn ingevoerd. Deze heb ik lekker - gemakkelijk gehouden. Vergelijk hem maar eens met de SAVE - procedure en je komt tot de ontdekking dat de namen omgekeerd - ingelezen worden. Wat bedoel ik? Als de namen in alfabetische - volgorde zijn weggeschreven (als voorbeeld), dan worden ze - anti-alfabetisch (dus net omgekeerd van Z naar A) ingelezen. - Let ook op de VAR (in de procedure-kop) bij Main en Names. - Bij Names is het altijd verplicht (een file kan niet in het - geheugen gekopieerd worden), maar bij Main zou ik het weg - kunnen laten. Of niet (een pointer kan in het geheugen - gekopieerd worden)? In dit geval niet!! - - Als er al ��n naam, of meerdere, ingevoerd waren, dan kon ik - het weglaten (moet de rest wel achteraan toegevoegd worden) - aangezien Main dan niet meer hoeft te veranderen (let vooral - op de voorgaande opmerking). Nu wordt elke nieuwe naam vooraan - in de lijst bijgeschoven en dus veranderd Main bij elke naam. - Conclusie : VAR kan niet weggelaten worden (anders ben je je - namen kwijt als je terugkeert naar het hoofdprogramma). - - Let ook op het gebruik van de EOF functie. Ik hou er rekening - mee dat een file verminkt is. Ik zou kunnen volstaan met de - EOF controle bij de WHILE-lus, maar als de file verminkt is, - dan gaat het fout bij het inlezen van het adres. Gevolg is een - crash van de computer en dus zijn al je gegevens weg. Let - hier op bij het programmeren van een grote toepassing. Let - tevens op de 'Close(Names)' aan het einde van de procedure, - deze is geplaatst om problemen te voorkomen indien je na het - inlezen het programma be�indigd (er staat immers nog een file - open). Verder bekend (neem ik aan) : - -PROCEDURE Loading(VAR Main:Point;VAR Names:Text); - - VAR - Temp : Point; - - BEGIN (* Loading *) - Assign(Names,'address.txt'); - Reset(Names); - WHILE NOT EOF(Names) DO - BEGIN - New(Temp); - IF NOT EOF(Names) THEN - Readln(Names,Temp^.Name) - ELSE - Temp^.Name:=''; - IF NOT EOF(Names) THEN - Readln(Names,Temp^.Address) - ELSE - Temp^.Address:=''; - Temp^.Next:=Main; - Main:=Temp; - END; - Close(Names); - END; (* Loading *) - - Ook deze procedure moet geen echte problemen opleveren (zeker - niet als je de vorige procedure begrepen hebt). Hier worden - namen toegevoegd aan de lijst (wederom vooraan). Ik houd er - rekening mee dat de gebruiker gekke dingen doet, vandaar de - dubbele controle op het invoeren van een lege regel. Let ook - op de twee Dispose opdrachten op het einde van de procedure!! - Again, read it and weep : - -PROCEDURE Adding(VAR Main:Point); - - VAR - Temp : Point; - - BEGIN (* Adding *) - New(Temp); - ClrScr; - Writeln('Adding an address to the list'); - Writeln; - Writeln; - Writeln('Give a name and an address (RETURN is stop).'); - Writeln; - Write('Give name : '); - Readln(Temp^.Name); - IF Temp^.Name<>'' THEN - BEGIN - Write('Give address : '); - Readln(Temp^.Address); - IF Temp^.Address<>'' THEN - BEGIN - Temp^.Next:=Main; - Main:=Temp; - END - ELSE - Dispose(Temp); - END - ELSE - Dispose(Temp); - END; (* Adding *) - - Aan deze procedure maak ik geen woorden vuil (buiten het feit - dat ik je wijs op het handige gebruik van de MOD functie bij - de REPEAT-UNTIL): - -PROCEDURE Print(Main:Point); - - VAR - Counter : integer; - Temp : Point; - - BEGIN - Temp:=Main; - Counter:=0; - REPEAT - ClrScr; - REPEAT - IF Temp<>NIL THEN - BEGIN - Writeln(Temp^.Name); - Writeln(Temp^.Address); - Temp:=Temp^.Next; - END - ELSE - BEGIN - Writeln; - Writeln; - END; - Writeln; - Counter:=Counter+1; - UNTIL (Counter MOD 7)=0; - Write('Press to continue.'); - Readln; - UNTIL Temp=NIL; - END; (* Print *) - - Dit is natuurlijk de meest interessante procedure. Je zou hem - nu echter (na het lezen van Laden en Plus) zo goed als moeten - kunnen dromen. Nee, dat is maar een grapje (NvdR: haha). - Zelfs ik heb moeten denken hoe je dit gemakkelijk en snel - zou kunnen oplossen. Door een truukje gebruik ik maar twee - hulppointers in plaats van drie (ik gebruik de Next van - Temp1 omdat die toch niet wordt gebruikt). Wat bij dit - soort procedures lastig is zijn niet de normale gevallen - (een naam middenin de lijst verwijderen), maar de bijzondere - gevallen (een naam in het begin of een naam op het einde - verwijderen). Probeer dit ook altijd goed uit als je zoiets - maakt, zodat je niet voor verassingen komt te staan. - Enjoy: - -PROCEDURE Min(VAR Main:Point); - - VAR - Temp1 : Point; - Temp2 : Point; - - BEGIN (* Min *) - New(Temp1); - ClrScr; - Writeln('Deleting an address from the list'); - Writeln; - Writeln; - Writeln('Give a name (RETURN is stop)'); - Writeln; - Write('Give name : '); - Readln(Temp1^.Name); - IF Temp1^.Name<>'' THEN - BEGIN - Temp2:=Main; - IF Main^.Name=Temp1^.Name THEN - BEGIN - Main:=Main^.Next; - Dispose(Temp2); - END - ELSE - BEGIN - WHILE Temp2<>NIL DO - IF Temp2^.Name<>Temp1^.Name THEN - BEGIN - Temp1^.Next:=Temp2; - Temp2:=Temp2^.Next; - END - ELSE - BEGIN - Temp1^.Next^.Next:=Temp2^.Next; - Dispose(Temp2); - Temp2:=NIL; - END; - END; - END; - Dispose(Temp1); - END; (* Min *) - - Tja, moet ik dit nog bespreken? Dacht het niet : - -PROCEDURE Saven(Main:Point;VAR Names:Text); - - VAR - Temp : Point; - - BEGIN (* Saven *) - Assign(Names,'adres.txt'); - Temp:=Main; - Rewrite(Names); - WHILE Temp<>NIL DO - BEGIN - Writeln(Names,Temp^.Name); - Writeln(Names,Temp^.Address); - Temp:=Temp^.Next; - END; - Close(Names); - END; (* Saven *) - - Hier wordt natuurlijk alles samengevoegd, maar dat het je al - begrepen: - - BEGIN (* MainProgramm *) - New(Main); - Main:=NIL; - welcome; - REPEAT - menu(choise); - CASE Choice OF - 1 : Loading(Main,Names); - 2 : Adding(Main); - 3 : Print(Main); - 4 : Min(Main); - 5 : Saven(Main,Names); - END; - UNTIL choise=6; - Temp:=Main; - WHILE Main<>NIL DO - BEGIN - Main:=Main^.Next; - Dispose(Temp); - Temp:=Main; - END; - END. (* MainProgramm *) - - Dat was het. Weinig commentaar van mij dit keer, maar dat komt - omdat je dit zelf moet uitzoeken. Het programma werkt (ik heb - het uitvoerig getest) en dus kun je hier kijken hoe het moet. - Wat je moet doen om zelf meer te leren is het programma - aanpassen (daar heb ik het voor gemaakt). Dit programma bevat - alleen maar de namen en adressen (dat adres is niet compleet) - en moet dus eigenlijk uitgebreid worden met postcode, - woonplaats en telefoonnummer. Vandaar de volgende opdrachten: - - (1) Verbeter de invoerroutines, zodat een en ander mooier - uitziet als er een fout wordt gemaakt. - (2) Breid het programma uit, zodat ook de postcode, - woonplaats en het telefoonnummer van de betrokkene - ingevoerd en bewaard kan worden. - (3) Sorteer de gegevens alfabetisch (Tip : maak gebruik van - een bubblesort algoritme, dat is het gemakkelijkst bij - pointers). - - Smael, wat is bubblesort? Bubblesort is een sorteerroutine. - Hoe werkt dat? Als volgt : - (1) X <- 1 - (2) Vergelijk element X en X+1 met elkaar - (3) ALS element X+1 < element X DAN - wissel element X en element X+1 - (4) X <- X+1 - (5) ALS nog elementen DAN - ga naar stap 2 - (6) ALS gewisseld (tijdens ��n doorgang) DAN - ga naar stap 1 - En gesorteerd is die hap. - - Bubblesort werkt dus met doorgangen. Per doorgang zorg je - ervoor dat minimaal 1 element op de goede plaats komt (je - schuift dat element telkens voor je uit). Na ��n doorgang heb - je dus alle elementen minimaal ��n maal bekeken. Zolang je dus - wisselt (al is het maar ��n keer per doorgang) ben je nog niet - klaar met sorteren. Dit lijkt niet effici�nt, maar is het wel - (bubblesort is ongeveer 5 keer sneller dan de ouderwetse - sorteermethode met de twee FOR-NEXT loops) en daarbij is het - ook nog eens het gemakkelijkst bij pointers (hoe wil je dat - met twee FOR-NEXT loops oplossen?). - - Zo, dat was het. Tot de volgende keer, dan gaan we het hebben - over recursie (en dat is pas ECHT leuk). Groetjes, - - -Red XIII diff --git a/Future Disk/36/Advanced Basic 5.md b/Future Disk/36/Advanced Basic 5.md deleted file mode 100644 index ecef032..0000000 --- a/Future Disk/36/Advanced Basic 5.md +++ /dev/null @@ -1,108 +0,0 @@ -Arjan bazelt wat over Advanced Basic... - - ADVANCED BASIC (5) - - - Welkom bij alweer het vijfde deel van deze cursus. Deze keer - ga ik het hebben over data-verplaatsingen, zoals ik de - vorige keer beloofd had. - - Het komt nogal eens voor dat je gegevens van ram naar vram - of andersom wilt verplaatsen. In BASIC gaat dit normaal - gesproken nogal traag en daarom heeft ADVANCED BASIC wat - extra commando's daarvoor, namelijk: - - _RAMRAM(startadres,aantal,bestemming) - Verplaatst aantal bytes vanaf startadres naar - bestemming. Een nuttig voorbeeld weet ik niet zo snel te - verzinnen. - - _RAMVRAM(startadres,aantal,bestemming,pagina) - Verplaatst aantal bytes van ram naar vram. Pagina is om - aan te geven of de 1e 64 kB of de 2e 64 kB vram als - bestemming gebruikt moet worden. Een voorbeeld: - 10 SCREEN 0 - 20 A$="Dit is een tekst ":HL=&HA000 - 30 FOR A=1 TO LEN(A$) - 40 POKE HL,ASC(MID$(A$,A,1)):HL=HL+1 - 50 NEXT A - 60 _RAMVRAM(&HA000,LEN(A$),240,0) - RUN - - Dit programmaatje zet een string in het geheugen en - verplaatst het naar adres 240 van het VRAM, wat in SCREEN 0 - de vierde regel is. - - _VRAMRAM(startadres,pagina,aantal,bestemming) - Verplaatst aantal bytes van vram naar ram. Een voorbeeld - lijkt me overbodig. - - _VRAMVRAM(startadres,pagina,aantal,bestemming,pagina) - Verplaatst aantal bytes van vram naar vram. Een leuk - voorbeeldje: - 10 SCREEN 0 - 20 PRINT "Deze tekst scrolled naar links" - 30 _VRAMVRAM(1,0,79,0) - 40 FOR A=1 TO 100:NEXT A - 50 IF STRIG(0)=0 THEN GOTO 30 - RUN - - Dit programmaatje print een tekstje en laat het naar links - scrollen en stopt pas als er op spatie gedrukt word. - - _OUTM(startadres,aantal,poort) - Stuurt aantal bytes vanaf startadres naar een I/O-poort. - Vooral handig bij de nieuwe MSX-uitbreidingen als OPL4 en - GFX9000. - - _INM(poort,aantal,bestemming) - Haalt aantal bytes uit I/O-poort en zet het in ram. Zie ook - _OUTM. - - - WHAT'S NEXT - - Verder heeft Advanced BASIC nog wat commando's om het (v)ram - met een waarde te vullen, namelijk: - - _FILLRAM(startadres,aantal,waarde) - Vult ram met een bepaalde waarde. Een voorbeeld: - 10 _FILLRAM(&H8000,128,0) - 20 PRINT "Deze tekst zie je niet meer...." - RUN - - Het programma wordt helemaal overschreven met nullen. De - tekst in regel 20 zul je dus niet meer te zien krijgen en - het programma stopt gewoon. - - _FILLVRAM(startadres,pagina,aantal,waarde) - Vult vram met een bepaalde waarde. Een voorbeeld: - 10 SCREEN 0 - 20 _FILLVRAM(0,0,24*80,65) - 30 IF STRIG(0)=0 THEN GOTO 30 - 40 CLS - RUN - - Dit programmaatje vult het hele scherm met de letter A. Na - een druk op de spatie kom je weer in BASIC. - - - WAT RESTJES - - Als laatst geef ik nog 2 commando's die niet zoveel met - data-verplaatsingen hebben te maken, namelijk: - - _GETPAL(kleur,rood,groen,blauw) - Leest de RGB-waardes van een kleur en zet die op de adressen - rood, groen en blauw. - - _HOME - Verplaatst de cursor van een window naar positie (0,0). - - De volgende en laatste keer komt hybride-programmeren onder - Advanced BASIC aan bod, waarmee je leuke dingen kunt doen - (onder andere Advanced BASIC combineren met KUN-BASIC!). Tot - dan! - - -Arjan Bakker diff --git a/Future Disk/36/Assembly cursus 5.md b/Future Disk/36/Assembly cursus 5.md deleted file mode 100644 index c29fd72..0000000 --- a/Future Disk/36/Assembly cursus 5.md +++ /dev/null @@ -1,110 +0,0 @@ -Arjan programmeert er rustig op los... - - ASSEMBLY (5) - - - Deze keer gaan we het hebben over screensplits, paletsplits - en alle andere soorten splits die je maar kunt bedenken. Een - goed voorbeeld van een screensplit zie je nu terwijl je aan - het lezen bent. Eigenlijk zijn er zelfs 2 screensplits, want - alleen de tekst beweegt en de border staat stil. - - Een split is eigenlijk heel simpel om te maken. Het kan - zelfs op 2 verschillende manieren. Je kunt namelijk de VDP - een interrupt laten genereren als de lijn voorbij is en je - kunt zelf testen of de VDP al voorbij de lijn is. Deze - laatste methode zal ik hier bespreken, de eerste komt een - volgende keer aan bod. - - Zoals gezegd is een split heel simpel. Eerst doe je nog wat - dingetjes totdat je denkt dat de VDP ongeveer is bij de lijn - waar je de split wilt hebben. Dan zet je in register 19 NA - welke lijn je de split wilt hebben. Daarna test je of bit 0 - van statusregister 1 een 1 is. Als dat zo is, is de VDP - klaar met die lijn. Vervolgens selecteer je een andere page, - schermmode, palet of whatever. Dit kost wel wat tijd, dus - zorg ervoor dat de lijnen bij de split dezelfde kleur - hebben want anders gaat die lijn knipperen. - - Een voorbeeldje: stel je wilt de helft van het scherm page 0 - hebben en de andere helft page 1. Dan zet je in register 19 - de waarde 105, dus komt de split bij lijn 106. Lijn 106 maak - je dan op beide pagina's dezelfde kleur en vervolgens test - je of de lijn al voorbij is. Daarna selecteer je page 1 en - dan wacht je weer op een interrupt om page 0 te selecteren. - - De volgende source zal het wel duidelijker maken. De source - staat ook op disk onder de naam SCRSPLIT.GEN. Natuurlijk is - er ook een klein voorbeeldje bij, namelijk SCRSPLIT.BAS, - welke deze routine gebruikt. Dit programmaatje laat ook zien - wat er gebeurt als je de lijnen bij de split niet dezelfde - kleur geeft. - - defb #fe ; BLOAD-header - defw start,einde,start - - org #d000 - - start: ei - halt - - ld a,31 ; 31 = page 0, 63 = page 1 - out (#99),a ; 127 = page 2, 255 = page 3 - ld a,2 + 128 - out (#99),a ; Selecteer page 0 - - xor a - call #d8 - or a - ret nz ; Spatie ingedrukt = stoppen - - ld a,105 ; Lijn voor screensplit - out (#99),a - ld a,19 + 128 - out (#99),a ; Stuur lijn naar register 19 - - ld a,1 - out (#99),a - ld a,15 + 128 - out (#99),a ; Selecteer statusregister 1 - nop - nop ; geef VDP wat tijd - split: in a,(#99) ; lees statusregister 1 - bit 0,A ; test bit 0 (0 = niet - ; voorbij lijn) - jp z,split ; herhaal test indien nodig - - ld a,63 - out (#99),a - ld a,2 + 128 - out (#99),a ; selecteer page 1 - - xor a - out (#99),a - ld a,15 + 128 - out (#99),a ; Selecteer statusregister 0 - - jp start ; herhaal - - einde: - - Een kleine opmerking wil ik nog maken over het selecteren - van statusregister 0. Dit register moet geselecteerd worden, - omdat de BIOS met IN A,(#99) dit register wil lezen terwijl - 'ie dit register meestal niet eerst selecteert (om tijd te - sparen). - - Als je maar ��n split hebt, hoef je register 19 maar ��n - keer te veranderen, zodat je weer (iets) meer tijd hebt voor - andere dingen. Dit heb ik hier niet gedaan voor de duidelijk- - heid. Natuurlijk is het mogelijk om meerdere splits te maken. - Je zet de routine voor de split vaker in je code, maar dan - telkens met een andere lijn. Zo simpel is dat. - - Dit was het dan voor deze keer. De volgende keer zal ik - .LIB-files behandelen (een file waar je alle files in - propt). Dat wordt een lekker lange aflevering, maar dat mag - ook wel eens een keertje, of niet soms? - - -Arjan Bakker diff --git a/Future Disk/36/Datacompressie 2.md b/Future Disk/36/Datacompressie 2.md deleted file mode 100644 index 24bba27..0000000 --- a/Future Disk/36/Datacompressie 2.md +++ /dev/null @@ -1,145 +0,0 @@ -Data compressie is een heel handig iets. Het zorgt ervoor dat je meer dan drie teksten per FD kan lezen, handig toch? - - DATA-COMPRESSIE (2) - - - De vorige aflevering van deze tekst eindigde met de - opmerking van Koenie dat ik de behandelde theorie iets meer - uit zou moeten werken en guess what: dat doe ik hier dan ook - (de klant is koning). Natuurlijk moet je zelf nog wat - knutselen aan deze routine's, want anders is er ook niets - aan. - - De (de-)cruncher is ontstaan omdat ik bezig was met een - muziekprogramma welke nu al tijden gecanceld is (NvdR: Cool, - heeft het muziekprogramma toch nog iets opgebracht!). - Ongecomprimeerde muziekdata neemt veel ruimte in beslag en - daarom maakte ik een simpele (de-)cruncher, welke 8 bytes - (wow!) kon crunchen. Natuurlijk zorgden de routine's - eromheen ervoor dat alles gecrunched werd, maar de basis was - 8 bytes, omdat er 8 bits in ��n byte zitten. - - Voor diegenen die de vorige deel niet hebben gelezen komt - hier eventjes een korte uitleg. In een file komen bepaalde - bytes vaak voor, zoals bijvoorbeeld in teksten de byte 32 (= - spatie) vaak voorkomt. Door nu voor elke byte met ��n bit - aan te geven of een byte gelijk is aan de byte die het meest - voorkomt, kun je (als het meezit) de files behoorlijk - kleiner maken. Een voorbeeldje: - - De file bestaat uit de volgende 16 bytes: - 0 25 4 0 3 0 0 195 0 5 201 0 0 0 65 32 - - De 0 komt het meest voor (8 keer). Door ��n bit te gebruiken - om aan te geven of een byte 0 is (bit geset) of ongelijk - (bit gereset), kun je de nullen achterwege laten en alleen - de andere bytes bewaren. Gecrunched komt de data er dan zo - uit te zien (de eerste byte van de regel is binair, de rest - is decimaal): - %10010110 25 4 3 195 - %10011100 5 201 65 32 - - De data is nu nog maar 10 bytes lang, een besparing van zo'n - 40%. Natuurlijk moet je de computer ook laten weten wat er - bedoeld wordt als een bit ��n is, dus kost het weer een byte - extra. - - - CRUNCH IT - - Hier volgt de crunch-routine, met achter de code wat - commentaar zodat het mogelijk moet zijn om deze routine te - begrijpen. - - ; Crunch-routine - ; In: HL: adres van ongecomprimeerde data - ; Uit: HL: adres van gecomprimeerde data - ; E: aantal bytes - ; Verandert: AF, BC, DE, HL, IX - crunch: ld ix,crubuf+1 ; adres waar ongecrunchde - ; bytes komen - ld d,0 ; geeft aan welke bytes - ; gecrunched zijn - ld e,1 ; Lengte gecrunchde data - ld b,8 ; 8 bytes te comprimeren - - crunc1: ld a,(hl) ; lees byte - inc hl - or a ; Gelijk aan 0 ? - jp z,crunc2 ; Ja -> crunc2 - ld (ix),a ; Nee -> sla waarde op - inc ix ; verhoog pointer - sla d ; Vul 0 in in statusbyte - inc e ; Verhoog aantal met 1 - djnz crunc1 ; herhalen - ld hl,crubuf - ld (hl),d ; bewaar status - ret ; finished! - - crunc2: sla d ; bits opschuiven - inc d ; Vul 1 in bij status - djnz crunc1 ; herhalen - ld hl,crubuf - ld (hl),d ; bewaar status - ret ; finished! - - crubuf: defs 9 ; Plek waar data komt - - Deze routine gaat er van uit dat de meest voorkomende byte 0 - is. Als je dit wilt aanpassen, moet je na de instructie - 'LD B,8' de instructie 'LD C,x" zetten, waarbij de x staat - voor het getal dat het meest voorkomt. Verder moet je 'OR A' - veranderen in 'CP C' en klaar is je routine. - - - DECRUNCH IT - - Okay, de crunch-routine was niet echt moeilijk h�! Dan volgt - hier nu de decrunch-routine, welke net zo simpel is! - - ; decrunch-routine - ; In: hl: data-string - ; Uit: hl: uitgepakte string - ; Verandert: AF, BC, DE, HL, IX - dcr: ld a,(hl) ; statusbyte - ld ix,dcrbuf ; Plek waar uncrunchde data - ; terecht komt - ld bc,8 * 256 ; 8 bytes (B), vulbyte=0 (C) - inc hl - - dcr1: add a,a ; Hoogste bit naar carry - jp c,dcr2 ; Carry gezet -> dcr2 - ld d,(hl) ; Haal byte uit gecrunchde - ld (ix),d ; data en bewaar het - inc hl ; verhoog pointers - inc ix - djnz dcr1 ; herhaal de zooi - ld hl,dcrbuf - ret ; finished! - - dcr2: ld (ix),c ; vul een nulletje in - inc ix ; Verhoog pointer - djnz dcr1 ; herhalen maar - ld hl,dcrbuf - ret ; finished! - - dcrbuf: defs 9 ; plek waar data komt - - - TOT SLOT - - Deze routine's zijn redelijk snel, zo'n 20kB per seconde is - toch wel te halen. Toch zijn er verbeteringen denkbaar, door - niet groepjes van 8 bytes te gebruiken, maar gewoon van ��n - byte. Je moet dan eerst ��n bit wegschrijven om aan te geven - of de data gecrunched is (1) of niet (0) en als de data niet - gecrunched is, bewaar je de te crunchen byte en kun je dit - herhalen. Dit is wel iets lastiger, omdat je dan met - bitstreams moet gaan werken. Het heeft dan wel als voordeel - dat de gecrunchte files iets kleiner worden, maar veel maakt - dat ook niet uit. - - De source van de uitgelegde routines staan ook op disk en - wel onder de naam CRUNCH.GEN. Veel plezier! - -Arjan Bakker diff --git a/Future Disk/36/Mathpack 2.md b/Future Disk/36/Mathpack 2.md deleted file mode 100644 index 1354380..0000000 --- a/Future Disk/36/Mathpack 2.md +++ /dev/null @@ -1,109 +0,0 @@ -Arjan heeft het over de Mathpack en ik snap er weer eens geen hout van... - - DE MATHPACK (2) - - - Een vorige keer schreef ik dat ik nog niet alle functies van - de MathPack had. Nu heb ik ze wel, dus kan ik weer een - lijstje met functies geven. Ik begin met ... - - - ...DATA-VERPLAATSINGEN - - Naam Adres Functie Type Verandert - MAF #2C4D DAC -> ARG Dubbele precisie A,B,D,E,H,L - MAM #2C50 (HL) -> ARG Dubbele precisie A,B,D,E,H,L - MOV8DH #2C53 (HL) -> (DE) Dubbele precisie A,B,D,E,H,L - MFA #2C59 ARG -> DAC Dubbele precisie A,B,D,E,H,L - MFM #2C5C (HL) -> DAC Dubbele precisie A,B,D,E,H,L - MMF #2C67 DAC -> (HL) Dubbele precisie A,B,D,E,H,L - MOV8HD #2C6A (DE) -> (HL) Dubbele precisie A,B,D,E,H,L - XTF #2C6F DAC <-> (SP) Dubbele precisie A,B,D,E,H,L - PHA #2CC7 (SP) -> ARG Dubbele precisie A,B,D,E,H,L - PHF #2CCC (SP) -> DAC Dubbele precisie A,B,D,E,H,L - PPA #2CDC ARG -> (SP) Dubbele precisie A,B,D,E,H,L - PPF #2CE2 DAC -> (SP) Dubbele precisie A,B,D,E,H,L - PUSHF #2EB1 (SP) -> DAC Enkele precisie D,E - MOVFM #2EBE (HL) -> DAC Enkele precisie B,C,D,E,H,L - MOVFR #2EC1 CBED -> DAC Enkele precisie D,E - MOVRF #2ECC DAC -> CBED Enkele precisie B,C,D,E,H,L - MOVRMI #2ED6 (HL) -> CBED Enkele precisie B,C,D,E,H,L - MOVRM #2EDF (HL) -> BCDE Enkele precisie B,C,D,E,H,L - MOVMF #2EE8 DAC -> (HL) Enkele precisie A,B,D,E,H,L - MOVE #2EEB (DE) -> (HL) Enkele precisie B,C,D,E,H,L - VMOVAM #2EEF (HL) -> DAC VALTYP B,C,D,E,H,L - MOVVFM #2EF2 (HL) -> (DE) VALTYP B,C,D,E,H,L - VMOVE #2EF3 (DE) -> (HL) VALTYP B,C,D,E,H,L - VMOVFA #2F05 ARG -> DAC VALTYP B,C,D,E,H,L - VMOVFM #2F08 (HL) -> DAC VALTYP B,C,D,E,H,L - VMOVAF #270D DAC -> ARG VALTYP B,C,D,E,H,L - VMOVMF #2710 (HL) -> DAC VALTYP B,C,D,E,H,L - - - REKENEN - - De volgende routine's zijn wel handig (niet allemaal, maar - de meeste wel): - - Naam Adres Functie Verandert - UMULT #314A DE = BC * DE Alles - ISUB #3167 HL = HL - DE Alles - IADD #3172 HL = HL + DE Alles - IMULT #3193 HL = HL * DE Alles - IDIV #31E6 HL = DE / HL Alles - IMOD #323A HL = DE mod HL Alles - - Het resultaat van deze functies komt ook op DAC+2 te staan - en VALTYP wordt op 2 gezet. Als je wilt rekenen, gebruik je - de routine's ISUB en IADD natuurlijk niet. De deling- en - vermenigvuldigingsroutine's zijn echter wel weer handig, als - je je code niet al te groot wilt laten worden tenminste. - - - VERGELIJKINGEN - - Met de volgende routine kun je getallen met elkaar - vergelijken. Na het aanroepen van een van deze functies - wordt in A een waarde teruggegeven. Als A 0 is, dan waren de - twee variabelen gelijk, als A 1 is, dan was de linker - variabele kleiner dan de rechter en als A 255 is, dan was de - linker groter dan de rechter variabele. De routines - veranderen overigens alle registers. - - Naam Adres Functie Precisie - FCOMP #2F21 Vergelijk CBDE met DAC Enkel - ICOMP #2F4D Vergelijk DE met HL Integer - XDCOMP #2F5C Vergelijk ARG met DAC Dubbel - - De routine ICOMP is wat mij betreft overbodig, want die zit - ook al gewoon in de BIOS (DCOMPR - RST #20) en meestal zal - je de code van die routine voor de snelheid ook al direct in - je routine zetten. - - - SLECHTE CODE - - Wat overigens opvalt bij het bestuderen van de routine's van - de Mathpack, is dat de routine's niet altijd gemaakt zijn op - snelheid. Zo kom je bijvoorbeeld de volgende source tegen - (met fictieve namen eventjes): - - move: ld a,(hl) - ld (de),a - inc hl - inc de - djnz move - ret - - Dit kun je veel beter gewoon met LDIR doen. Register C wordt - dan wel aangepast wat eerder niet gebeurde, dus even - PUSH'en, POP'en register B 0 maken is wel noodzakelijk. Op - een Turbo R kun je dit makkelijk aanpassen (bij de - RAM-mode), op een MSX2(+) zal het heel wat meer moeite - kosten. - - De volgende keer komen de resterende routine's van de - MathPack aan bod. - - - Arjan Bakker diff --git a/Future Disk/36/ROM images laden.md b/Future Disk/36/ROM images laden.md deleted file mode 100644 index c19e4b8..0000000 --- a/Future Disk/36/ROM images laden.md +++ /dev/null @@ -1,112 +0,0 @@ -ROM images, laat IK daar nu geen reet van snappen. - - ROM-IMAGES LADEN - - - Op de CD's van MCCM staan heel wat rom-images. Ook op andere - CD's (die illegaal zijn) en via internet (idem dito) zijn - heel wat roms te verkrijgen. Op een MSX-emulator zijn deze - eenvoudig te gebruiken, maar op een MSX is het een stuk - lastiger. - - Er is een programmaatje dat rom-images inlaadt en start, - maar bij mij werken de meeste spelletjes niet of niet - goed. Ik heb geen DOS2, dus ik denk dat het daar aan ligt. - In deze tekst zal ik beschrijven hoe je een programaatje - kunt maken en toch rom-images (van 16kB) kunt gebruiken, en - natuurlijk staat een simpele lader ook op de FD. - - De rom-images beginnen met de letters AB en vervolgens 2 - bytes die het adres weergeven waar na initialisatie heen - wordt gesprongen. De letters AB mag je wissen, zodat het - spel niet automatisch opstart na het resetten. - - De 2 bytes na AB kun je gebruiken om te kijken op welk adres - je het programma moet zetten. Als het adres groter is dan - #3FFF, dan kun je de rom-image op het interval #4000-#7FFF - laden en anders vanaf adres #0000. - - Verder moet er op pagina 1 en soms op 0 ram geschakeld zijn. - Onder DOS is dit altijd het geval, maar onder BASIC niet. Je - kunt met het volgende programmaatje op pagina 1 tot en met 3 - hetzelfde ram-slot selecteren. Als op pagina 0 ook RAM moet - staan, dan moet je vier keer RRA gebruiken in plaats van - twee keer. - - in a,(#a8) ; Lees huidige stand - and 240 ; Hoogste 4 bits zijn onder - ld b,a ; BASIC altijd al RAM - rra ; Schuif de bits naar rechts - rra - or b ; Oude stand erbij - out (#a8),a ; Schrijf slotstand weg - - Zo, nu weet je alles om een 16kB rom-image te gebruiken. Nu - gaan we daadwerkelijk het programma maken (niet helemaal - natuurlijk, maar alleen de code waar je problemen mee kunt - krijgen. De volledige source staat op deze FD in de file - ROM16.LZH, waar ook een simpele BASIC-lader in staat) - waarmee je 16kB rom-images mee kunt inladen. Het programma - aanpassen voor 32kB is trouwens erg makkelijk. - - org #c000 - - Onder BASIC erg logisch, want op adres #4000-#7FFF mag niets - geladen worden. - - ld de,fcb - ld c,open_file - call bdos ; open de rom-image - - call initFCB ; initialiseer FCB om te - ; laden - - ld de,#8000 - ld c,setdta ; Zet adres waar de data - call bdos ; terecht komt - - ld hl,16384 - ld de,fcb - ld c,read_block - call bdos ; Lees file in - - di ; Interrupts uit - - call selram ; Schakel RAM in - - ld hl,#8000 ; Wis A van AB zodat rom niet - ld a,0 ; na reset opstart - ld (hl),a - ld bc,#4000 ; Grootte - ld de,#4000 ; Bestemming - ld a,(#8003) ; Check startadres van rom - cp #40 - jp nc,jump1 ; >#4000 -> Bestemming is - ; goed - - ld de,#0000 - - jump1: ldir ; Verplaats - - ld hl,(#8002) ; Laadt start adres - jp (hl) ; en spring ernaar toe - - - Het gebruik van ROM-images die groter dan 32kB zijn is veel - lastiger, omdat die schakelroutine's gebruiken die bij - bepaalde roms de data op andere adressen schakelen dan bij - andere roms. Daarom heeft fMSX bij het selecteren van roms - een optie om de cartridge-type te kiezen, zodat de roms wel - werken. Het programma LOADROM (voor MSX) kan wel mega-roms - aan, maar dat programma werkt alleen onder DOS2 goed en laat - ik die nou net niet hebben. Een ander probleem is het - geheugen, want bij mega-roms heb je gewoon meer dan 128kB - geheugen nodig. Ook een probleem is dat de roms zelf ook - naar ram schrijven en dus je kopie kunnen overschrijven - waardoor alles in de soep loopt. - - - Veel plezier en succes! - - -Arjan Bakker diff --git a/Future Disk/36/Recursie 2.md b/Future Disk/36/Recursie 2.md deleted file mode 100644 index c4f7d42..0000000 --- a/Future Disk/36/Recursie 2.md +++ /dev/null @@ -1,121 +0,0 @@ -Dit is alweer het negende en laatste deel van de PASCAL cursus door de enige echte Jeroen Smael (NvdR: yeaaaah!!)... - - RECURSIE - - - ���� Ja, je leest het goed, dit deel gaat over recursie. Dat - ���� is ook waar we vorige keer gebleven waren, dus..... - ���� Goed, niet te veel intro gezeik, ik ga gewoon beginnen - ���� en dan zien we wel waar we uitkomen. - - Recursie (2) - - Wat is recursie? Recursie is (letterlijk) herhalen. Wat kun je - ermee? Heel veel, maar dat zal (hopelijk) nog wel duidelijk - worden. Een klassiek voorbeeld van recursie is machtsverheffen. - - MACHTSVERHEFFEN - - Wat is machtsverheffen? - - x^n = x^(n-1)*x - x^(n-1) = x^(n-2)*x - x^(n-2) = x^(n-3)*x - - Ok, je begrijpt het nu wel. De vraag is alleen wanneer stop ik - (terminate). Ik stop als (n-?) gelijk aan 0 is. Waarom? Als - (n-?) gelijk aan nul is dan krijg ik x^0 en dat is ALTIJD 1. - De functie ziet er dan als volgt uit: - - PROCEDURE Macht2(n : integer) : integer; - - BEGIN - IF n=0 THEN - Macht2=1 - ELSE - Macht2=Macht2(n-1)*2 - END; - - Bovenstaand is om elke willekeurige (positieve) macht van 2 te - berekenen (dat zit immers niet standaard in PASCAL). - Bijzonderheden zijn dat de functie zichzelf aanroept - (Macht2=Macht2(n-1)*2). Dat zou eigenlijk niet kunnen, omdat - de functienaam eigenlijk alleen aan de linkerkant van het = - teken mag staan (voor een toewijzing). Maar mag in dit geval - wel. - - IS DIT ALLES? - - Nee, dit is nog lang niet alles, maar het volgende (en tevens - laatste) voorbeeld is wel iets lastiger. Waarom? Omdat dit een - voorbeeld van backtracking is. Wat is Backtracking? - Backtracking wordt gebruikt voor zoek algoritmen. - - Backtracking - - Stel je staat in een doolhof. Wat doe je? Je gaat zoeken - natuurlijk, maar hoe? Als een kip zonder kop lijkt me niet erg - verstandig, want dan kom je nooit waar je wil zijn (de - uitgang). Dus ga je systematisch zoeken. Maar hoe doe je - dat? Als je veel tijd hebt (en wat heb je anders in een - doolhof) dan ga je altijd rechts. Is dat niet meer mogelijk, - dan ga je rechtdoor. Gaat dat niet meer, dan ga je links. Gaat - dat niet meer, dan ga je terug tot de plaats waar je als - laatste een keus moest maken en doet daar hetzelfde. Op die - manier kom je waar je wezen moet (bij de uitgang). Wat je - natuurlijk niet moet doen (maar wat ik vergeten ben te zeggen) - is over je eigen weg lopen (dus als je er al geweest bent, dan - ga je niet verder, omdat je anders in een kring gaat lopen). - - - Implementatie - - Ik ga de pseudo code van de implementatie geven, zodat je die - zelf uit kunt werken. Je moet dan wel zelf de hele - datastructuur opzetten, want dat doe ik niet voor je. Hier - gaat 'ie: - - PROCEDURE ZoekUitgang(Doolhof , Locatie , Gevonden); - - BEGIN - IF Locatie is buiten THEN - Gevonden = TRUE - ELSE - BEGIN - IF mogelijk naar rechts THEN - ZoekUitgang(Doolhof(markeer Locatie) , - Locatie + 1 naar rechts , Gevonden); - IF NOT Gevonden & mogelijk naar voren THEN - ZoekUitgang(Doolhof(markeer Locatie) , - Locatie + 1 naar voren , Gevonden); - IF NOT Gevonden & mogelijk naar links THEN - ZoekUitgang(Doolhof(markeer Locatie) , - Locatie + 1 naar links , Gevonden); - END; - END; - - Dat is alles. Hier horen natuurlijk een paar opmerkingen bij - en wel de volgende: - - Doolhof is een array waar de doolhof in staat en tevens of - je er geweest bent. - - Locatie is je 'X en Y' positie in de doolhof - - mogelijk is een functie die aangeeft of je die richting uit - mag (dit kun je ook de de procedure ZoekUitgang laten doen, - aangezien in een muur ook niet buiten is). - - markeer locatie is in Doolhof aangeven dat je er geweest - bent (dat moet je daarna wel weer verwijderen, anders zoek - je niet alles af). - - - WAT MOET IK ZEKER WETEN - - Wat je zeker moet weten is dat de MSX Turbo PASCAL v3.3 geen - recursie aankan. "Wat, geen recursie, waarom heb je ons dit - dan allemaal verteld?" - Omdat je recursie wel aan kunt zetten. Hoe? Door de $A+ optie - te gebruiken. Vergeet dit niet, anders klopt er niets van je - baksels (zelfs het machtsverheffen werkt dan al niet). - - Dat was het, - - Jeroen 'Backtracking' Smael diff --git a/Future Disk/37/Advanced Basic 6.md b/Future Disk/37/Advanced Basic 6.md deleted file mode 100644 index 42384c4..0000000 --- a/Future Disk/37/Advanced Basic 6.md +++ /dev/null @@ -1,102 +0,0 @@ -Een zeer nuttige tekst... - - ADVANCED BASIC CURSUS 6 - - - Eindelijk, het laatste deel van deze cursus. Ik heb het - gevoel dat geen hond zich interesseert in deze cursus. - Het aantal personen die Advanced BASIC kochten zijn op een - hand te tellen, ondanks de goede recensies. Blijkbaar - programmeert niemand meer in BASIC, of is men gewoon te - gierig om wat geld uit te geven? Hoe dan ook, dit is het - laatste deel van deze cursus en daar ben ik blij om. Nu kan - ik wat meer tijd zinniger besteden, bijvoorbeeld aan het - programmeren van een MoonSound-replayer voor de FD. - - - ENOUGH CRAP - - Goed, ik zal maar snel verdergaan met de cursus, want daar - gaat het toch om. Zoals gezegd gaat deze aflevering over - hybride-programmeren onder Advanced BASIC. Hybride - programmeren wil zeggen dat er 2 of meer programmeertalen - met elkaar gecombineerd worden, zoals BASIC met ML of PASCAL - met ML. - - BASIC is over het algemeen prima te combineren met ML, maar - wat toch onhandig is, is het doorgeven van veel parameters - aan de routines. Meestal is het een kwestie van de hele zooi - ergens POKE'n, maar dat is niet echt netjes. Met Advanced - BASIC gaat dit een stuk makkelijker, want je kunt namelijk - gewoon met CALL REGreg(x) een waarde aan een register geven. - Alle registers zijn toegestaan, op de stackpointer, program- - counter en de registers I en R na. - - Nadat je alle registers hebt gevuld, kun je met _CALL(adres) - een ML-routine op het aangegeven adres gebruiken. Je kunt de - ML-routine's natuurlijk ook met DEFUSR=x:A=USR(0) aanroepen, - maar dan worden er geen registers doorgegeven. - - Natuurlijk kun je, als je de registers kunt wijzigen, ook de - registers weer uitlezen. Dit kan met het commando CALL - GETreg(adres). Het register aangeduidt met 'reg' wordt dan - gezet in het aangegeven adres. Zoals al in een vorige deel - van deze cursus gezegd werd, kun je met een truukje ook een - variabele als bestemming gebruiken. Dit gaat als volgt: - 10 DEFINT A-Z - 20 _CALL(&H9F) - 30 T=0:_REGA(VARPTR(T)) - 40 PRINT CHR$(T) - RUN - - Dit programmaatje roept routine CHGET op adres &H9F aan, - welke de ingedrukte toets in register A zet. Vervolgens kun - je met VARPTR(T) het adres van variabele T krijgen en dat - adres wordt dus gevuld met de waarde van de ingedrukte - toets. Tot slot wordt de ingedrukte toets eventjes geprint. - Let erop dat als je VARPTR(var) gebruikt, de variabele al - wel moet bestaan. Daarom wordt de variabele T eerst - aangemaakt in regel 30. Doe je dit niet, dan krijg je een - botte Illegal function call. De variabele moet trouwens ook - integer zijn, anders kan het fout gaan. - - -ADVANCED BASIC & KUN-BASIC - - Advanced BASIC en KUN-BASIC kunnen met elkaar gecombineerd - worden. Je moet wel eventjes een heel klein programmaatje - maken, maar dat is zo simpel als wat. De truuk is dat je de - beide uitbreidingen allebei in een andere geheugenpagina zet - en de juist pagina inschakelt als je een extra commando wilt - gebruiken. - - Het volgende programmaatje laad Advanced BASIC en KUN-BASIC - in het geheugen: - - 10 OUT &HFD,2:BLOAD "ADVBASIC.BIN",R - 20 OUT &HFD,4:BLOAD "COMPILER.BIN",R - - Als je nu een commando van Advanced BASIC wilt gebruiken, - schakel je eerst Advanced BASIC in met OUT &HFD,2 en dan kun - je het commando gebruiken. Wil je KUN-BASIC gebruiken, dan - kun je die inschakelen met OUT &HFD,4. - - Een nadeel is dat je geen commando's van Advanced BASIC - binnen een stuk programma dat gecompileerd wordt. Het - volgende kan dus niet: - 10 OUT &HFD,4 ' Schakel KUN in - 20 _TURBO ON - 30 PRINT "This won't work" - 40 OUT &HFD,2 ' Schakel Advanced BASIC in - 50 _WINDOW(0,0,80,3) - 60 OUT &HFD,4 ' Schakel KUN in - 70 _TURBO OFF - RUN - - Het programma loopt nu vast op het commando _WINDOW. - - Als het goed is, heb ik nu alle commando's behandeld. Zo - niet, pech gehad, want ik heb geen zin om ook nog maar ��n - woord aan dit onderwerp vuil te maken. - - Arjan Bakker diff --git a/Future Disk/37/Assembly cursus 6.md b/Future Disk/37/Assembly cursus 6.md deleted file mode 100644 index dac6008..0000000 --- a/Future Disk/37/Assembly cursus 6.md +++ /dev/null @@ -1,830 +0,0 @@ -De assembly cursus gaat vrolijk verder... - - ASSEMBLY (6) - - - Zoals ik de vorige keer al zei ga ik het deze keer hebben - over .LIB-files. Omdat dit nogal een uitgebreid onderwerp - is, beslaat deze tekst 3 delen. Het eerste deel behandelt - wat theorie en een klein stukje van de source van de - LIB-maker, deel twee gaat over de rest van die source en - deel 3 van deze cursus legt uit hoe je .LIB-files moet - gebruiken in je eigen programma's. - - - WAT ZIJN LIB-FILES? - - Een LIB-file is niets anders dan een file waarin alle files - die een programma gebruikt zitten (vandaar LIB, van - LIBrary). Een goed voorbeeld van deze files is bijvoorbeeld - Smumpkin 3, Muzax 3 en de Final Fantasy Slide Show die op - disk A van FD 35 stond. - - - WAAROM LIB-FILES? - - Waarom zou je LIB-files gebruiken als het gebruiken van - gewone files veel makkelijker is? Hier is een aantal redenen - voor, namelijk: - - -Het neemt minder ruimte in beslag: Stel je hebt 4 files van - (ik noem maar wat) 256 bytes. Als deze files los in de - directory zouden staan, namen ze ieder (op een diskette) - ��n kilobyte in beslag, dus met z'n allen is dat 4 kB. In - een LIB-file nemen ze echter maar 1 kB in beslag, omdat de - files aan elkaar worden geplakt. - - -Het is sneller: Telkens als een nieuwe file wordt geopend, - moet de computer de juiste filenaam in de directory zoeken. - Dit kost aardig wat tijd, zeker als de directory helemaal - vol staat en de te zoeken file de laatste file uit de - directory is. Een andere manier om snel te laden is alles - op sector zetten. Dit neemt wel minder ruimte in beslag dan - gewoon de bestanden op diskette houden, maar LIB-files zijn - altijd nog effici�nter. - - -Er passen (in theorie) oneindig veel files in: In een - directory passen (normaal gesproken) slechts 112 files. - Het aantal files in een LIB-file is echter oneindig, voor - zover de diskruimte het toelaat tenminste. - - -Het is veel netter dan gewoon alle files op disk kwakken: - Een directory vol met bestanden is niet echt netjes, zeker - als je meerdere programma's op ��n diskette zet. - - - NADELEN - - Er zijn natuurlijk ook wat nadelen aan het gebruik van - LIB-files, namelijk: - - -De directory van een LIB-file moet permanent in het - geheugen staan (hoeft eigenlijk niet, maar het is wel v��l - sneller). Een erg groot nadeel is dit niet, want meestal - zal je directory niet meer dan 1 kB in beslag nemen. De - routine die straks volgt gebruikt per file 16 bytes, dus - met 64 files heb je 1 kB vol. Gebruik je echter de - effici�ntste methode, dan kun je in 1 kB ruim 200 files - zetten! Dit lijkt mij meer dan genoeg. - - -Het is wat extra programmeerwerk. Dit valt in de praktijk - echter best wel mee, zelfs ik had er geen moeite mee. Dit - geldt natuurlijk alleen voor de eerste keer, want je - volgende programma's kun (moet) je gebruik maken van - dezelfde routine's. - - -DE OPZET VAN HET PROGRAMMA - - Ik heb gekozen voor een programma dat onder DOS werkt, om de - simpele reden dat daar gewoon meer geheugen beschikbaar is. - Verder verwacht het programma de bestanden op drive A en - komt de LIB-file op drive B. Dit is echter zeer makkelijk - aan te passen. Harddisk-gebruikers zullen gewoon alles op - ��n drive doen, net zoals mensen met maar ��n diskdrive - (tenzij je een lekker grote ramdisk aan kunt maken). Ook - zijn er geen foutmeldingen. Tot slot staan de namen van de - bestanden die in de LIB-file moeten komen in de source zelf, - evenals de naam van de aan te maken LIB-file. Dit heb ik - gedaan om de source niet al te lang te laten worden, want - een command-line interpreter kost aardig wat regeltjes. Ook - is het niet de bedoeling dat ik alles voorkauw, en - natuurlijk ben ik lui! Een andere geldige reden is dat de - ruimte van de command-line aardig beperkt is. De beste - oplossing zou gewoon zijn om alle bestanden in een tekstfile - te zetten en de naam daarvan door te geven aan het - programma. Maar goed, dat mogen jullie zelf allemaal wel - doen. - - - DE SOURCE - - Okay, dan komt nu het programma zelf. - - org #0100 - - bdos: equ #05 - setdta: equ 26 ; zet lees/schrijf-adres - open_file: equ 15 ; open file - close_file: equ 16 ; sluit file - create_file: equ 22 ; maak file aan - read_block: equ 39 ; laad van disk - write_block: equ 38 ; schrijf naar disk - - entry_length: equ 11 + 2 + 3 - - Het programma werkt onder MSX-DOS, dus een org #0100 is op - z'n plaats (alhoewel dit wel weggelaten kan worden bij - GEN80. Zo is het echter voor jezelf wel duidelijk dat het - een DOS-programma is). Verder worden wat naampjes voor disk- - gebruik gedefinieerd en de lengte die de naam en data van - een bestand in de directory moet innemen. Dit is hier in - totaal 16 bytes, namelijk 11 voor de filenaam, 2 voor de - lengte en 3 voor de plaats in de LIB-file. Dit heeft echter - als beperking dat de maximale grootte van een file die in de - LIB-file moet komen 64kB is. Deze grootte zul je echter - alleen maar overschrijden bij samplekits voor de Moonsound, - dus zo'n ramp is dat ook weer niet. Ik ga verder... - - MAIN - - call count_files ; tel aantal files - ld (files),bc - - call calc_length ; bereken lengte - ; directory - ld (dir_length),hl - - call make_dir ; maak directory - - call save_dir ; bewaar directory - - call store_files ; bewaar files - - ld de,fcb2 - ld c,close_file - call bdos ; klaar! - ret - - Dit is de hoofdlus van het programma. De routine count_files - telt het aantal files die in de LIB-file moeten komen, - calc_length berekent de lengte van de directory, make_dir - maakt de directory aan, save_dir schrijft de directory weg - en store_files copi�ert alle files naar de LIB-file. - Tenslotte wordt de LIB-file gesloten en zijn we klaar. - - COUNT FILES - - ; Tel aantal files - ; In: - - ; Uit: BC: aantal files - ; Verandert: AF,BC,DE,HL - count_files: ld hl,file_names - ld bc,0 - ld de,11 - - count_files1: ld a,(hl) - or a - ret z - inc bc - add hl,de - jr count_files1 - - Deze routine telt het aantal files in de directory. Dit - wordt gedaan door te kijken of de byte op adres HL een 0 is. - Als dat zo is, zijn alle files geteld en anders wordt BC - verhoogd en wordt de zooi herhaald. - - - CALCULATE LENGTH - - ; Bereken lengte directory - ; In: BC: aantal files - ; Uit: HL: lengte directory - ; Verandert: AF, BC, DE, HL - calc_length: ld hl,3 - ld de,entry_length - - calc_length1: ld a,b - or c - ret z - add hl,de - dec bc - jr calc_length1 - - Deze routine berekent de lengte van de directory. Dit wordt - gedaan door dom de waarde entry_length herhaald op te tellen - en vervolgens er 3 bij op te tellen. De eerste 2 bytes van - de directory worden namelijk gebruikt om het aantal files - in de directory aan te geven en de laatste byte van de - directory wordt gebruikt om aan te geven dat alle files - geweest zijn. Natuurlijk kan het berekenen sneller gedaan - worden door een vermenigvuldigingsroutine te gebruiken, maar - dit was eventjes wat sneller om te programmeren (ja, ik ben - lui!). - - De routine om de directory te maken is behoorlijk lang, - daarom zal ik tussen de regels door wat opmerkingen maken en - niet pas aan het einde. - - - MAKE DIRECTORY - - ; Maak directory - ; In: HL: lengte directory - ; Uit: - - ; Verandert: AF, BC, DE, HL - make_dir: ld (getal1),hl - ld hl,0 - ld (getal1+2),hl - - ld hl,file_names - ld de,directory - ld bc,(files) - - Dit stukje initialiseert de routine. Op het adres 'getal1' - staat de offset waar de files na de directory van de - LIB-file beginnen. Verder wordt het adres waar de filenamen - staan geladen (HL), het adres waar de directory moet komen - geladen (DE) en het aantal files geladen (BC). - - make_dir1: push bc - - push hl - push de - - ld bc,11 - ld de,fname1 - ldir ; filenaam naar FCB - - pop de - pop hl - ld bc,11 - ldir ; filenaam naar directory - - Register BC hebben we pas op het einde weer nodig dus - PUSH'en we die even weg. Vervolgens moet de filenaam twee - keer gecopi�erd worden, namelijk naar de FCB en naar de - uiteindelijke directory. - - push hl - - push de - ld de,fcb1 - ld c,open_file - call bdos - ld de,fcb1 - ld c,close_file - call bdos - pop de - ld hl,(length1) - - De file wordt geopend en de lengte wordt opgevraagd. - - ld a,l - ld (de),a - inc de - ld a,h - ld (de),a - inc de - - De lengte van de file wordt in de directory gezet. - - ld ix,getal1 ; bewaar positie in file - ld a,(ix) - ld (de),a - inc de - ld a,(ix+1) - ld (de),a - inc de - ld a,(ix+2) - ld (de),a - inc de - - De plek waar de file in het bestand staat wordt in de - directory gezet. Dit is een 24-bits getal, daarom wordt dit - eventjes met register IX gedaan. - - push de - - ld iy,getal2 - ld (iy),l - ld (iy+1),h - ld ix,getal1 - call add_32bit - - De lengte van de file wordt opgeteld bij de positie in de - LIB-file. Hiervoor wordt een 32-bits optel-routine gebruikt, - welke 'getal1' en 'getal2' gebruikt als parameters en het - resultaat stopt in 'getal1'. - - pop de - pop hl - pop bc - dec bc - ld a,b - or c - jp nz,make_dir1 - xor a - ld (de),a - ret - - Nu worden alle registers teruggehaald en wordt er een lusje - gemaakt om de boel te herhalen. Als alle files geweest zijn, - wordt er nog even een 0 weggeschreven en dan is deze routine - klaar. - -LEES VERDER IN DEEL 2 -De assembly cursus gaat vrolijk verder... - - ASSEMBLY (6)-2 - - -We gaan weer verder waar we gebleven waren... - - - SAVE DIRECTORY - - ; Bewaar directory - ; In: - - ; Uit: - - ; Verandert: AF, BC, DE, HL - save_dir: ld hl,lib_name - ld de,fname2 - ld bc,11 - ldir - - ld de,fcb2 - ld c,create_file - call bdos ; cre�er file - - call intfcb2 - - ld de,files - ld c,setdta - call bdos - - ld de,fcb2 - ld c,write_block - ld hl,(dir_length) - call bdos ; schrijf directory weg - ret - - Deze routine bewaart de net aangemaakte directory. Eerst - wordt de naam van de library naar het FCB gecopi�erd. - Vervolgens wordt de file gecre�erd en wordt het FCB - geinitialiseerd voor het schrijven. Daarna wordt het Disk - Transfer Address gezet op het adres waar het aantal files - staat en tot slot wordt de directory weggeschreven. - - - STORE FILES - - ; Bewaar files in .LIB-file - ; In: - - ; Uit: - - ; Verandert: AF, BC, DE, HL - store_files: ld bc,(files) - ld hl,file_names - - Het aantal files wordt in register BC geladen en het adres - waar de filenamen staan in register HL. - - store_files1: push bc - - ld bc,11 - ld de,fname1 - ldir - push hl - - call clrfcb1 - - ld c,open_file - ld de,fcb1 - call bdos - - call intfcb1 - - De filenaam wordt gecopi�erd naar het FCB, het FCB wordt - vervolgens schoongemaakt en daarna wordt de file geopend. - Tot slot wordt het FCB ge�nitialiseerd. - - ld hl,(length1) - call copy_file ; kopieer file - - ld de,fcb1 - ld c,close_file - call bdos - - pop hl - pop bc - dec bc - ld a,b - or c - jp nz,store_files1 - ret - - In register HL komt de lengte van de file en die wordt - vervolgens gecopi�erd door de routine copy_file. De file - wordt daarna gesloten en dan wordt het zooitje herhaald. - - - COPY FILE - - ; Copieer file naar .LIB-file - ; In: HL: lengte file - ; Uit: - - ; Verandert: AF, BC, DE, HL - copy_file: push hl - ld c,setdta - ld de,directory - call bdos - pop hl - - Het lees/schrijfadres wordt op het adres gezet waar de - directory stond. - - copy_file1: ld de,32768 - xor a - sbc hl,de ; file >32768 bytes? - jp c,copy_file2 ; Nee, copieer rest - - push hl - ld hl,32768 - ld de,fcb1 - ld c,read_block - call bdos - - ld hl,32768 - ld de,fcb2 - ld c,write_block - call bdos - pop hl - jp copy_file1 - - Er wordt gekeken of de file groter is dan 32 kB. Als dat zo - is, dan wordt er 32 kB ingeladen en vervolgens wegge- - schreven. Daarna wordt de routine herhaald. - - copy_file2: add hl,de - push hl - ld de,fcb1 - ld c,read_block - call bdos - pop hl - ld de,fcb2 - ld c,write_block - call bdos - ret - - De resterende data van de file wordt ingelezen en weggeschreven - - ; Tel twee 32-bits getallen op - ; In: IX: adres getal 1 - ; IY: adres getal 2 - ; Uit: getal 1 gevuld met resultaat - ; Verandert: BC,DE,HL - add_32bit: ld l,(ix+0) - ld h,(ix+1) - - ld e,(iy+0) - ld d,(iy+1) - - ld c,(ix+2) - ld b,(ix+3) - add hl,de - jr nc,add_32bit1 - inc bc - add_32bit1: ld (ix+0),l - ld (ix+1),h - - Deze routine telt twee 32-bits getallen bij elkaar op. In IX - staat het adres van het eerste getal en in IY het adres van - het tweede getal. Register HL en DE worden geladen met het - eerste word van de 32-bits waarde en register BC met het - tweede word van het eerste getal. Daarna wordt DE bij HL - opgeteld en als er een overflow plaats vindt, wordt het - tweede word met ��n verhoogd. Tot slot wordt het eerste word - weggeschreven. - - ld l,(iy+2) - ld h,(iy+3) - add hl,bc - ld (ix+2),l - ld (ix+3),h - ret - - Het tweede word van het tweede getal wordt in register HL - geladen en wordt bij het tweede word van het eerste getal - opgeteld en vervolgens opgeslagen. - - ; Maak FCB 1 schoon - ; In: - - ; Uit: - - ; Verandert: AF, BC, DE, HL - clrfcb1: ld hl,fcbdat1 - ld bc,25 - xor a - ld (hl),a - ld de,fcbdat1 + 1 - ldir - ret - - Deze routine maakt het eerste FCB snel schoon met een - truukje met LDIR. Het eerste adres wordt namelijk eerst op 0 - gezet en het bestemmingsadres wordt dan ��n hoger dan het - beginadres. Met LDIR wordt vervolgens het FCB gevuld met - nullen. - - ; Initialiseer FCB 1 - ; In: - - ; Uit: - - ; Verandert: AF, HL - intfcb1: ld hl,0 - ld (fcb1 + 12),hl - ld (fcb1 + 33),hl - ld (fcb1 + 35),hl - xor a - ld (fcb1 + 32),a - inc hl - ld (fcb1 + 14),hl - ret - - Deze routine initialiseert het eerste FCB voor het lezen. - Het current block (fcb1 + 12) wordt op 0 gezet, evenals - random record (fcb1+32/33/35). Tot slot wordt de record- - lengte op 1 gezet. - - ; Initialiseer FCB 2 - ; In: - - ; Uit: - - ; Verandert: AF, HL - intfcb2: ld hl,0 - ld (fcb2 + 12),hl - ld (fcb2 + 33),hl - ld (fcb2 + 35),hl - xor a - ld (fcb2 + 32),a - inc hl - ld (fcb2 + 14),hl - ret - - Deze routine doet hetzelfde als de routine intfcb1. - - getal1: defw 0,0 ; opslagplaats voor de twee - getal2: defw 0,0 ; 32-bits getallen - - dir_length: defw 0 ; lengte van directory - - ; Het eerste FCB - fcb1: defb 1 ; drive (0=default, 1 = A:) - fname1: defm " " - fcbdat1: defb 0,0,0,0 - length1: defb 0,0,0,0,0,0,0,0,0,0,0 - defb 0,0,0,0,0,0,0,0,0,0,0 - - ; Het tweede FCB - fcb2: defb 2 ; drive (0=default, 2 = B:) - fname2: defm " " - defb 0,0,0,0,0,0,0,0,0,0,0,0,0 - defb 0,0,0,0,0,0,0,0,0,0,0,0,0 - - ; Naam van de te maken .LIB-file - lib_name: defm "???????????" - - ; Lijst met files die in de .LIB-file moeten - file_names: defm "???????????" - - defb 0 ; 0 = laatste gehad - - files: defw 0 ; bewaarplaats aantal files - directory: nop - - Vul bij lib_name de aan te maken LIB-file in en bij - file_names de bestanden die je erin wilt hebben. De lengte - van de naam is 11 letters en er mag GEEN '.' gebruikt - worden. Na de laatste file moet een 'defb 0' staan, om aan - te geven dat er geen files meer komen. - - -LEES VERDER IN DEEL 3 -De assembly cursus gaat vrolijk verder... - - ASSEMBLY (6)-3 - - -We gaan weer verder waar we gebleven waren... - - Tot slot bespreek ik de routine's om de LIB-files in je - eigen programma's te gebruiken (m��r wil ik ook niet meer - doen). Deze routine's zijn stukken simpeler, daarom besteed - ik ook maar ��n tekst aan dit gedeelte. - - Er zijn drie routine's nodig, namelijk een routine die de - file opent en de directory inleest, een routine die een file - opzoekt in de directory en de pointers goed zet en een - routine die een (gedeelte van een) file inlaadt. - - - DE SOURCE - - bdos: equ #f37d - fopen: equ 15 ; open file - fclose: equ 16 ; sluit file - rdblk: equ 39 ; lees blok - setdta: equ 26 ; zet lees/schrijfadres - - ; Routine's voor het gebruik van een .LIB-file - init_dir: jp load_dir ; laad directory in - file_find: jp search_file ; Zoek file - load_file: jp load_block ; Laad file in - - Dit zijn de routine's die het inlezen van de directory, het - zoeken van een file in de directory en het lezen van een - file uitvoeren. - - - LOAD DIRECTORY - - ; Laad directory - ; In: HL: Adres filename - ; DE: Bestemmingsadres directory - load_dir: push de - push de - push hl - - call clrfcb - - pop hl - - ld bc,11 - ld de,fname - ldir - - pop de - ld c,setdta - call bdos - - Het FCB wordt schoongemaakt, de naam van de LIB-file wordt - in het FCB gezet en vervolgens wordt het lees/schrijf-adres - gezet. - - ld de,fcb - ld c,fopen - call bdos - - call intfcb - - ld hl,2 - ld de,fcb - ld c,rdblk - call bdos - - De file wordt geopend, het FCB wordt ge�nitialiseerd en het - aantal files in de directory wordt gelezen (eerste 2 bytes). - - pop hl - ld c,(hl) - inc hl - ld b,(hl) - - ld hl,1 - ld de,11 + 3 + 2 ; lengte entry - calc_length: add hl,de - dec bc - ld a,b - or c - jp nz,calc_length - - Het aantal files komt in BC terecht en de lengte van de - directory wordt berekend. Dit kan wel beter met een echte - vermenigvuldigingsroutine, maar dit was eventjes sneller - programmeren. - - ld de,fcb - ld c,rdblk - call bdos ; Laad directory in - ret - - De directory wordt geladen en klaar is de routine. - - - SEARCH FILE - - ; Zoek file op in directory en stel record number in - ; In: HL: adres te laden file-naam - ; DE: adres directory - ; Uit: HL: lengte file - ; A: 0 indien gelukt, 255 indien mislukt - search_file: push hl - push de - - call cmp_str - - or a - jp z,search_file1 - - De file wordt vergeleken met de huidige file in de directory. - Als A nul is, is de file gevonden. - - pop de - ld hl,11 + 3 + 2 - add hl,de - ex de,hl ; DE = positie in directory - pop hl - jp search_file - - De pointer naar de directory wordt verhoogd en de routine - herhaalt zichzelf. - - search_file1: ex de,hl ; HL = adres in directory - - ld e,(hl) - inc hl - ld d,(hl) ; laad lengte - inc hl - push de - - De lengte van de file wordt uitgelezen en gePUSHed. - - ld de,fcb + 33 - ld bc,3 - ldir ; Record Number naar FCB - - xor a - ld (de),a - - De positie in de file wordt in het FCB gezet. - - pop hl ; lengte in HL - - pop de - pop de - ret - - De lengte van de file komt in HL en de routine is klaar. - - LOAD (PART OF) FILE - - ; Lees een (gedeelte van een) file in - ; In: HL: aantal te laden bytes - ; Opmerking: zelf bestemmingsadres goedzetten - load_block: ld de,fcb - ld c,rdblk - jp bdos - - Geen uitleg nodig lijkt mij. - - ; Vergelijk strings met elkaar - ; In: HL: adres eerste string - ; DE: adres tweede string - ; Uit: A: 0 = gelijk, anders = ongelijk - cmp_str: ld b,11 - - cmp_str1: ld a,(de) - cp (hl) - ret nz - inc hl - inc de - djnz cmp_str1 - xor a - ret - - Vergelijk twee strings met elkaar. Ook hier geen uitleg - nodig, lijkt mij. - - ; Initialiseer FCB - ; in: niets - ; uit: niets - ; Verandert: alles - clrfcb: ld hl,fcbdat - ld bc,25 - xor a - ld (hl),a - ld d,h - ld e,l - inc de - ldir - ret - - Zie vorige tekst. - - ; init fcb - ; in: niets - ; uit: niets - ; Verandert: af, hl - intfcb: ld hl,0 - ld (fcb+12),hl ; bloknummer op 0 - - ld (fcb+33),hl ; random block op 0 - ld (fcb+35),hl - - xor a - ld (fcb+32),a ; current record op 0 - - inc hl - ld (fcb+14),hl ; bloklengte op 1 - ret - - Zie vorige tekst. - - ; file control block - fcb: defb 0 ; drive - fname: defm "???????????" ; filename - fcbdat: defb 0,0 ; current block - defb 0,0 ; block lengte - length: defb 0,0,0,0 ; file lengte - defb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - - Ook in deze routine's zijn natuurlijk weer verbeteringen - mogelijk. Zo zou je een error kunnen laten geven als een - file niet gevonden wordt, al is dat niet echt nodig als je - een programma uitbrengt. - - De sources staan natuurlijk ook op disk. De library-maker - heet MAKELIB.GEN en de library-lezer heet USELIB.GEN. Het is - niet verboden om de sources in je eigen programma's te - gebruiken, maar het is beter als je je eigen routine's - maakt. Tot de volgende keer! - - Arjan Bakker diff --git a/Future Disk/37/Mathpack 3.md b/Future Disk/37/Mathpack 3.md deleted file mode 100644 index 835f849..0000000 --- a/Future Disk/37/Mathpack 3.md +++ /dev/null @@ -1,91 +0,0 @@ -Het laatste deel over de MATH PACK... - - DE MATH-PACK (3) - - - In dit laatste deel over de math-pack komen de wat comple- - xere routine's aan bod, en dan voornamelijk de string- - routine's. - - De routine FIN (&H3299) zet een string om naar een decimaal - getal in DAC. Hiervoor heeft deze routine register HL nodig - om het startadres van de string aan te geven en register A om - het eerste teken te weten. Als resultaat staat op DAC dus het - getal. Register C bevat de waarde 255 als de string geen punt - bevatte en de waarde 0 als er wel een punt in stond en regis- - ter B bevat het aantal cijfers achter de punt. - - De routine's FOUT (&H3425) en PUFOUT (&H3426) zetten het - getal in DAC om naar een string. Het verschil tussen beide - routine's is dat FOUT de string niet formatteerd en PUFOUT - wel en dat PUFOUT de DAC positief maakt. - - De invoer en uitvoer is bij beide routine's hetzelfde. - Register A geeft het formaat van de string aan, waarbij de - afzonderlijke bits de volgende betekenis hebben: - - bit 7: 0 = ongeformatteerd, 1 = geformatteerd - bit 6: 0 = zonder komma's , 1 = met komma's om de drie - cijfers - bit 5: 0 = niets , 1 = voorafgaande spaties worden - opgevuld met punten - bit 4: 0 = niets , 1 = "$" wordt voor de waarde - gezet - bit 3: 0 = niets , 1 = "+" wordt voor de waarde - gezet (indien de waarde positief was) - bit 2: 0 = niets , 1 = +/- wordt achter de waarde - gezet - bit 1: niet gebruikt - bit 0: 0 = fixed point , 1 = floating point - - Register B geeft het aantal cijfers voor de punt aan en - register C geeft het aantal cijfer na de punt aan (inclusief - de punt). Als er dus 3 tekens na de punt komen, moet je de - waarde 4 in register B zetten. - - Na het uitvoeren van ��n van deze routine's komt in register - HL het adres van de string. - - De routine's FOUTB (&H371A), FOUTO (&H371E) en FOUTH - (&H3722) zetten een integer getal in DAC+2/3 om naar - respectievelijk een binaire, octale en hexadecimale string. - Let er trouwens op dat VALTYP op 2 staat. Deze 3 routine's - hebben dus als resultaat een string waarvan het beginadres - in register HL komt te staan. - - - TYPE CONVERSIE - - De routine's FRCINT (&H2F8A), FRCSNG (&H2FB2) en FRCDBL - (&H303A) zetten het getal DAC om naar respectievelijk een - 2-byte integer (DAC+2/3), een enkele precisie waarde en een - dubbele precisie waarde. Na aanroep bevat VALTYP het type - van DAC (dus 2, 4 of 8) en zijn alle registers veranderd. - - De routine FIXER op adres &H30BE maakt van het getal DAC een - gehele waarde. Ook hier worden alle registers veranderd. - - - MACHTSVERHEFFEN - - Er zijn nog 3 extra routine's voor het machtsverheffen. - SGNEXP (&H37C8) is voor getallen van enkele precisie, DBLEXP - (&H37D7) is voor getallen van dubbele precisie en INTEXP - (&H383F) is voor 2-byte integers. De eerste 2 routine's - gebruiken DAC als basis en ARG als macht en de laatste - gebruikt DE als basus en HL als macht. Bij alle drie de - routine's wordt het resultaat in DAC gezet en worden alle - registers verandert. - - TOT SLOT - - Er is ook nog een routine om register HL decimaal op het - scherm te zetten, namelijk PRTHL (&H3412). Deze routine is - echter niet offici�el, maar werkt volgens mij wel altijd. - - Ik geloof dat ik nu wel alles over de math-pack heb - behandeld. Mocht ik echter nog wat onbehandelde dingetjes - tegenkomen, dan zal ik daar later op terugkomen maar wat mij - betreft is dit de laatste tekst over dit onderwerp. - -Arjan Bakker diff --git a/Future Disk/38/Assembly cursus 7.md b/Future Disk/38/Assembly cursus 7.md deleted file mode 100644 index e5fa8bd..0000000 --- a/Future Disk/38/Assembly cursus 7.md +++ /dev/null @@ -1,138 +0,0 @@ -ASSEMBLY CURSUS 7 - - -Dit is alweer het zevende deel van de assembly cursus, -tenminste, als ik me niet vergis. Maar goed, het is niet -echt belangrijk om te weten welk deel het is want dat maakt -geen zak uit voor de inhoud. En nu ik het toch over de -inhoud heb, ik heb de laatste tijd moeite om een leuk onder- -werp te verzinnen. Mocht je dus eens een keer iets willen -weten, schrijf of bel ons even en wellicht krijg je op de -volgende FD dan al een antwoord. Maar goed, voor deze keer -heb ik nog wel een onderwerpje, namelijk werken met BCD- -getallen - - - BCD-GETALLEN - -Het idee voor dit onderwerp kreeg ik tijdens het maken van -het spelletje dat deze keer op de FD staat. Ik had namelijk -lange getallen nodig om de score aan te duiden en dan heb je -aan 16 bits niet genoeg. Je kunt dan wel gaan werken met 32 -bits getallen, maar het afdrukken daarvan gaat niet echt -snel en het is ook een beetje lastig om te programmeren. - -Nu zal een ervaren programmeur natuurlijk zeggen: Waarom -gebruik je niet de MathPack (MP)? Nou, dat zal ik eens -eventjes fijn uitleggen. Ten eerste is de MP mij te sloom, -omdat de MP ook rekening houdt met een komma, negatieve -getallen en een exponent, en dat heb ik allemaal niet nodig. -Ten tweede...hmm, ik weet geen tweede reden te verzinnen, -maar de reden die ik opgaf was voor mij al genoeg om de MP -maar niet te gebruiken. - -Goed, BCD-getallen dus. BCD wil niets anders zeggen dan -Binary Coded Decimal. In gewoon Nederlands houdt dit in dat -je met 4 bits ��n getal aangeeft en dat betekent dat je met -1 byte 2 getallen kunt weergeven. Een klein voorbeeldje om -alles te illustreren: - -9 is en blijft negen. -19 wordt &b0001 1001 = &h19 -52 wordt &b0101 0010 = &h52 - -Okee, dit lijkt me nu wel duidelijk. Nu is een notatie -natuurlijk niet genoeg om de getallen te kunnen gebruiken, -want zonder correctie zou bijvoorbeeld 19 (=&h19) + 52 -(=&h52) 107 (=&h6b) worden en dat is dus niet goed, want het -goed antwoord zou &h71 moeten zijn. Bij aftrekken gaat het -ook fout (&h52 - &h19 = &h39, het goede antwoord is echter -&h33). - -Gelukkig kent de Z80 een hele handige instructie om het -resultaat te corrigeren, namelijk DAA. Dit betekent Decimal -Adjust Accumulator. Deze instructie test eerst op de H-flag -(bit 4). Als deze geset is (zoals bij ons het geval was), -dan moet het getal gecorrigeerd worden en anders natuurlijk -niet. - -Als er een getal gecorrigeerd moet worden, kijkt de Z80 naar -de N-flag (bit 1). Deze flag geeft aan of er een aftrekking -of een optelling plaats vond. Let op: deze instructie werkt -alleen als er ADD of SUB gebruikt werd. Als er een getal -afgetrokken werd, moet register A met 6 verlaagd worden en -anders juist met 6 verhoogd worden. Tot slot wordt de Carry- -flag geset als het resultaat niet in een BCD-getal past (b.v. -99 (&h99) + 2 (&h02) = 101 (&h01). Hier wordt de carry dus -geset). - -Met deze informatie zou je zelf een optel/aftrek-routine -kunnen maken voor BCD-getallen. Een kleine tip: reken van -achter naar voren en gebruik ADC/SBC om te rekenen. Mocht je -er niet uitkomen, lees deze tekst dan nog eens of kijk eens -in de file CALC.GEN (staat op deze FD) en dan zal het wel -duidelijk zijn. - - - RLD/RRD - -Voor het vermenigvuldigen/delen van BCD-getallen is het -handig om getallen ��n plek naar links of naar rechts op te -kunnen schuiven. Hiervoor heeft de Z80 ook instructies, -namelijk RLD en RRD. Het gebruik hiervan is ietwat lastiger -dan bij gewone schuifinstructies, maar echt lastig is het -ook weer niet. - -De instructies RLD/RRD verschuiven getallen via register A -en het getal op adres HL, waarbij RLD natuurlijk naar links -schuift en RRD naar rechts. De werking van de instructies -blijkt uit het volgende schemaatje: - -RLD: - >--->--->--->---> - ! ! - &b0000 0000 &b0000 0000 - ! ! ! ! - <---<---<--- <--- - reg A (HL) - -RRD - <---<---<---<---< - ! ! - &b0000 0000 &b0000 0000 - ! ! ! ! - --->--->---> ---> - reg A (HL) - -Om alles nog wat duidelijker te maken, komen hier nog twee -voorbeeldjes: - -RLD: -A: &h04 -HL: &hC000 -(HL): &h59 - -Na afloop van de instructie RLD is het resultaat: - -A: &h05 -HL: &hC000 -(HL): &h94 - -RRD: -A: &h04 -HL: &hC000 -(HL): &h59 - -Na afloop van de instructie RRD is het resultaat: - -A: &h09 -HL: &hC000 -(HL): &h45 - -Volgens mij moeten jullie nu ook wel in staat zijn om een -vermenigvuldigings-routine te programmeren. Als het toch -niet lukt, kijk dan eventjes naar de routines in CALC.GEN -en dan zal alles (hoop ik) wel duidelijk zijn. - - -Arjan diff --git a/Future Disk/40/Assembly cursus 8.md b/Future Disk/40/Assembly cursus 8.md deleted file mode 100644 index 8833c29..0000000 --- a/Future Disk/40/Assembly cursus 8.md +++ /dev/null @@ -1,63 +0,0 @@ -# ASSEMBLY (8) - - De vorige keer hebben jullie deze rubriek moeten missen - vanwege inspiratiegebrek, maar voor deze keer heb ik toch - iets weten te verzinnen, namelijk het gebruiken van extra - opties bij een DOS-programma (dus bv PRINT FD.TXT, waarbij - PRINT.COM een programma is om een tekst naar de printer te - sturen en FD.TXT de af te drukken tekst is). - - Het kunnen gebruiken van die extra optie is heel simpel. Op - adres #80 staat het aantal tekens dat na het commando werd - ingevoerd en op adres #81 en verder staat de ingevoerde - tekst. Het aantal tekens is overigens exclusief de byte #0d - (Carriage Return). Hier volgt een (heel simpel) voorbeeld- - programmaatje: -``` - org #0100 - - bdos: equ 5 - strout: equ 9 - - ld a,(#0080) ; aantal tekens - or a - jr z,notext ; 0 tekens = geen tekst - - ld e,a ; aantal bytes - ld d,0 - ld hl,#0081 - add hl,de ; pointer naar einde tekst+1 - ld a,"$" - ld (hl),a ; vervang #0d door "$" - - ld de,#0081 - ld c,strout - call bdos ; print string - ret - - ;geen tekst ingevoerd - notext: ld de,text - ld c,strout - call bdos ; print tekstje - ret - - text: defb "No text entered$" -``` - Dit programmaatje staat ook op disk, zowel de source als de - geassembleerde file, welke ASSEMB8.GEN en ASSEMB8.COM heten. - - -## CACHE-ROUTINES - - Ongeveer een jaar geleden heb ik voor de FD eens een cache- - routine geschreven. Deze is echter nooit gebruikt, voor- - namelijk omdat de MoonSound-replayer erg veel ruimte - gebruikt. De volgende keer zal ik deze cache-routine's - bespreken, want daar heb ik nu vanwege de toch wel krappe - deadline echt geen tijd voor. Voor de liefhebbers staat de - source wel op disk (CACHE.GEN). Oh ja, deze cache-routine - cached alleen sectoren, geen files. Misschien maak ik voor - de volgende keer ook nog een cache-routine voor files, maar - dat zien jullie dan wel. - -Arjan diff --git a/Future Disk/40/Schuiven en roteren.md b/Future Disk/40/Schuiven en roteren.md deleted file mode 100644 index 3e00875..0000000 --- a/Future Disk/40/Schuiven en roteren.md +++ /dev/null @@ -1,131 +0,0 @@ -# SCHUIVEN & ROTEREN - - De moeilijkste commando's die de Z80 kent, zijn wat mij - betreft wel de schuif- en roteerinstructies, en dan wel met - name het gedoe rond het gebruik van de carry-flag. Zelfs - mijn MSX Machinetaalboek (Dullin/Strassenburg) gaat op dit - gebied de mist in. Gelukkig staan daar ook copi◊n van de - Z80-tabellen in, waar alles uiteraard correct instaat, dus - dat maakt het wel weer goed, maar lastig blijven de - instructies wel. - - De schuifinstructies zijn overigens wel makkelijk, maar - omdat schuif-instructies dicht bij roteerinstructies zitten, - neem ik ze hier toch maar mee. De instructies RLD en RRD - laat ik hier buiten beschouwing. Op een vorige FD (38 geloof - ik) is hier meer informatie over te vinden. - - -## SCHUIVEN MAAR - - Er zijn 3 verschillende (offici◊le) soorten schuifinstruc- - ties, namelijk SLA, SRA en SRL. Deze instructies kunnen als - parameter meekrijgen: een register (A,B,C,D,E,H,L) of een - pointer ( (HL),(IX+d),(IY+d) ). - - De instructie SLA is te vergelijken met een vermenigvuldi- - ging van 2. De bits worden rekenkundig (de letter A van SLA) - ÇÇn plaatsje naar links (de letter L) geschoven (de letter - S), waarbij bit 0 nul wordt en de oorspronkelijke bit 7 in - de carry-flag komt. - - De instructie SRA en SRL doen allebei ongeveer hetzelfde: - delen door 2. De bits worden ÇÇn plaatsje naar rechts - geschoven en bit 0 komt in de carry-flag terecht. Het - verschil tussen SRA en SRL is dat bij SRA bit 7 gelijk - blijft (zodat signed getallen correct gedeeld worden), - terwijl bij SRL bit 7 nul wordt. - - -## ROTEER ZE - - Het hele probleem van de roteer-instructies wordt veroor- - zaakt door de naamgeving van de instructies. Volgens mijn - logica zou de instructie RLCA de bits van register A naar - links schuiven, waarbij bit 7 in de carry-flag terecht komt - en de oude carry-flag in bit 0 komt. Het zou dus eigenlijk - ee soort 9-bits rotatie opleveren. Dit is echter niet het - geval. RLCA schuift de bits wel ÇÇn positie naar links, en - bit 7 komt ook wel in de carry-flag terecht, maar in plaats - van dat de oude carry-flag in bit 0 terecht komt, komt bit 7 - terecht in bit 0! Een voorbeeldje om alles duidelijk te - maken: - - Register A bevat de waarde &B01000001 ofwel 65 en de carry- - flag is gezet. Na een RLCA instructie wordt register A - &b10000010 (bit 0 wordt 0 omdat bit 7 nul was) en de - carry-flag wordt gereset (bit 7 was immers gereset). - - De instructie RLA daarentegen zou volgens mijn logica de - bits ook ÇÇn positie naar rechts schuiven, waarbij bit 7 in - de carry-flag terecht komt en bit 0 gelijk aan de oude bit 7 - wordt. Dit is echter niet het geval, want bij RLA wordt bit - 0 niet gelijk aan de oude bit 7, maar gelijk aan de oude - carry-flag! Weer even een voorbeeldje om alles duidelijk te - maken: - - Register A bevat de waarde &b01000001 ofwel 65 en de carry- - flag is gezet. Na een RLA instructie wordt register A - &b10000011 (bit 0 wordt 1 omdat de carry-flag gezet was) en - de carry-flag wordt gereset (omdat bit 7 oorspronkelijk - gereset was). - - Helemaal onlogisch is de naamgeving niet. De letter C uit de - instructie RLCA staat namelijk voor Circular (rondgaand in - het Nederlands), waarmee de makers proberen duidelijk te - maken dat de bits in hetzelfde register blijven. Wat mij - betreft is dit w◊l onlogisch, aangezien de instructie RLA - ook circulair is, alleen duurt het daar een ronde voordat - een oorspronkelijk bit weer terugkomt (na 9 keer RLA bevat - de accumulator weer de oorspronkelijke waarde, terwijl dit - bij RLCA na 8 keer al het geval is). - - De namen van de instructies zouden eigenlijk omgewisseld - moeten worden, waarbij de letter C de betekenis 'with Carry- - flag' ofwel 'met Carry-flag' zou moeten krijgen. De makers - van de R800 zagen dit ook in, daar heet de Z80-instructie - RLCA (die RLA zou moeten heten) ROLA (zonder C dus) en de - instructie RLA heet ROLCA, zoals het volgens mijn logica ook - zou moeten zijn (afgezien van die extra 'O' dan). - - Er zijn overigens wel meer instructies van naam verandert - bij de R800. Wat te denken van ROL4 (HL) in plaats van RLD, - of, nog leuker, MOVEM (HL++),(DE++) in plaats van LDIR. Maar - nu dwaal ik af geloof ik. - - Terug naar de roteerinstructies. Afgezien van het gedoe rond - die carry-flag, hebben de instructies wel een logische naam. - De eerste letter, R, staat voor Rotate. De tweede letter kan - een R of een L zijn. R betekent Right en L betekent dus - Left, om aan te geven welke richting de bits geschoven - moeten worden. Tot slot KAN er de letter C volgen. Als deze - er staat, betekent het (onlogisch) dat de carry-flag NIET - naar bit 0 getransporteerd wordt, zonder de letter C gebeurt - het (ook weer onlogisch) w◊l. - - De roteer-instructies kunnen dezelfde parameters krijgen als - de schuif-instructies, dus daar maak ik geen woorden meer - aan vuil. - - -## RLCA = RLC A??? - - Van de instructies die met de accumulator werken, bestaan er - twee versies, namelijk: -``` - RLCA en RLC A - RLA en RL A - RRCA en RRC A - RRA en RR A -``` - Het is een misverstand om te denken dat de instructies uit - de linker kolom hetzelfde doen als de instructies uit de - rechter kolom. De meeste programmeurs weten wel dat de - instructies uit de linker kolom een byte korter en twee keer - zo snel zijn, maar dat de flag-be◊nvloeding anders is weet - bijna niemand. Bij de instructies RLCA/RLA/RRCA en RRA - worden de zero-flag, de P/V-flag en de Sign-flag namelijk - niet be◊nvloed, terwijl dit bij de langere versies van deze - instructies wel het geval is. Let hier dus goed op!!! - -Arjan \ No newline at end of file diff --git a/Future Disk/42/Assembly cursus 9.md b/Future Disk/42/Assembly cursus 9.md deleted file mode 100644 index 171b885..0000000 --- a/Future Disk/42/Assembly cursus 9.md +++ /dev/null @@ -1,453 +0,0 @@ -Leest iemand dit? - - ASSEMBLY CURSUS 9 (1) - - - - OEPS OEPS OEPS... - - ...en nog eens oeps. Vorige keer stond in deze cursus dat er - een source van een cache-routine op disk zou staan. Dat was - helaas niet geval. Als het goed is, staat het dingetje nu - w�l op deze FD, en wel onder de naam CACHE.GEN. - - Vorige keer had ik ook beloofd om die cache-routine te - bespreken. Aangezien belofte schuld maakt, doe ik dat nu dan - maar ook. De routine in kwestie kan alleen sectoren cachen, - dus geen files. Daar had ik namelijk geen zin in, maar - misschien komt het er ooit nog eens van. Misschien ook - niet... - - - KESJING - - Caching is niets anders dan bepaalde informatie in het - geheugen op te slaan. In het geval van MSX betekent dat - bepaalde informatie maar ��n keer vanaf diskette ingeladen - hoeft te worden, mits er natuurlijk genoeg geheugen aanwezig - is (meestal meer dan 128 kB). Ik zal eerst maar eens globaal - uitleggen hoe de cache-routine die op deze FD staat werkt. - - Ergens in het geheugen staat een tabel van 2880 (1440 - sectoren * 2 bytes). Elk byte-paar geeft aan waar een sector - in het geheugen staat. Als beide bytes 0 zijn, dan staat de - sector nog niet in het geheugen, anders wel. De eerste byte - geeft aan in welke mapper-page de sector staat, de tweede - byte geeft aan op welk adres (#4000-#7fff) de sector staat. - Let op: dit byte is alleen de hi-byte! Deze opzet is vooral - handig als een hele diskette gecached moet kunnen worden. - Het is namelijk het makkelijkst en het snelst. - - De routine gebruikt dus 2 bytes voor het opslaan van de plek - waar de gecachde sector staat, namelijk ��n voor de - mapper-page en ��n voor het adres. Na elke gecachde sector - wordt het adres met 512 verhoogd, maar aangezien de - adres-pointer alleen de hi-byte bijhoudt, wordt deze met 2 - verhoogd (2*256=512). Zodra het adres boven #8000 uitkomt, - wordt deze teruggezet op #4000 en wordt de mapper-page met - ��n verhoogd. - - Nu ga ik verder met de source. Tussen de source door zal ik - af en toe wat extra informatie geven. - - Eerst eventjes wat constanten... - - bdos: equ #f37d - enaslt: equ #0024 - - setdta: equ 26 - diskrd: equ 47 - - minimum_pages: equ 9 - first_page: equ 8 - - De eerste 4 equ's hebben geen commentaar nodig, lijkt me. De - waarde minimum_pages geeft aan hoeveel pages van 16kB er - nodig zijn om de cache-routine te kunnen gebruiken. Het - geheugen moet trouwens in ��n slot zitten (daar wordt de - routine namelijk simpel van). In dit geval zijn er 9 blokken - van 16 kB nodig, dus een geheugen van 144kB of meer is - vereist. De waarde first_page geeft aan welke mapper-page - als eerste gebruikt wordt de cache-routine. Ik ga verder met - de source. - - init: jp init_cache - read: jp read_sectors - - Dit zijn de entries voor het gebruik van de cache-routine. - De routine 'init' initialiseert de cache-routines en 'read' - wordt gebruikt om sectoren te lezen (vanaf diskette of - vanuit RAM). Ik ga weer verder. - - init_cache: call count_map ;count number of pages - cp minimum_pages ;enough memory - jr c,no_cache ;no? -> no caching possible - - Eerst wordt de routine 'count_map' aangeroepen om te kijken - hoeveel geheugen er aanwezig is. Het aantal blokken wordt in - de accumulator gezet. Vervolgens wordt gekeken of er wel - genoeg geheugen is om caching toe te passen. Als er te - weinig geheugen aanwezig is, dan wordt er gesprongen naar de - routine 'no_cache'. Nog meer source... - - ld (number_pages),a ; store number of - available pages - - ld a,first_page ;first page to put - sectors in - ld (next_page),a - ld a,#40 ;first address of - cached sectors - ld (next_address),a - - ld hl,cache_table - ld de,cache_table + 1 - ld bc,1440 * 2 - 1 - ld (hl),0 - ldir ; clear cache-table - ret - - Het aantal aanwezige mapper-pages wordt opgeslagen, de - geheugen-pointers worden ge�nitialiseerd en de cache-table - wordt geleegd. - - ; no caching possible - no_cache: ld hl,read_disk1 - ld (read + 1),hl - ret - - De entry 'read' wordt omgebogen, zodat een aanroep meteen - tot diskactie leidt. Caching was immers niet mogelijk... - - ; Count number of pages in memory mapper - ; Out: A: number of pages - count_map: in a,(#fe) - push af - call store_old - call check_map - call restore_old - pop af - out (#fe),a - ld a,d - or a - ret nz - dec a - ret - - Deze routine kijkt hoeveel geheugen er in de primaire mapper - zit. 'store_old' bewaard alle bytes die zich op #8000 - bevinden, zodat er geen geheugen verloren gaat door het - onderzoeken van de mapper-grootte. 'check_map' telt het - aantal aanwezige mapper-pages. 'restore_old' herstelt het - geheugen weer en tot slot wordt er nog even gekeken of het - aantal mapper-pages 0 is (=256 = 4MB). Als dat zo is, dan - wordt het aantal pages gelijk aan 255 gemaakt (da's meer dan - genoeg). - - ; save old mapper data - store_old: ld bc,0 - ld hl,cache_table - - store_old_lp: ld a,c - out (#fe),a - ld a,(#8000) - ld (hl),a - xor a - ld (#8000),a - inc hl - inc c - djnz store_old_lp - ret - - Dit stukje code bewaard de originele geheugen-inhoud. Op - adres wordt de waarde 0 gezet, zodat later gezien kan worden - dat dit stukje geheugen nog niet geteld is. - - ; Count number of pages - ; Out: D: number of mapper pages - check_map: ld d,0 - - check_map_lp: ld a,d - out (#fe),a - - ld a,(#8000) - or a - ret nz - - dec a - ld (#8000),a - - inc d - jr check_map_lp - - Deze routine telt het aantal aanwezige mapper-pages. Als er - op adres #8000 een 0 staat, dan is de huidige page niet - meegeteld en kan het aantal pages met ��n verhoogd worden. - - ; Restore old mapper data - ; In: D: number of mapper-pages - restore_old: ld c,0 - ld b,d - ld hl,cache_table - - restore_old_lp:ld a,c - out (#fe),a - - ld a,(hl) - ld (#8000),a - - inc hl - inc c - djnz restore_old_lp - ret - - Hier wordt de oorspronkelijke geheugeninhoud weer hersteld. - -LEES VERDER IN DEEL 2! - - Leest iemand dit? Stuur dan een briefje of E-mailtje naar de redactie! - - ASSEMBLY CURSUS 9 (2) - - - We gaan vrolijk door waar we gebleven waren... - - ; Read sectors - ; In: L: drive (0=A, 1=B) - ; DE: first sector - ; H: number of sectors - ; BC: destinationaddress - read_sectors: push hl - - ld hl,cache_table - add hl,de - add hl,de - ld a,(hl) - or a ;already cached? - jp nz,read_cache - - Eerst wordt gekeken of de sector al gecached is. Als dat zo - is (A<>0) dan wordt naar de routine read_cache gesprongen - waar de sector vanuit RAM gelezen wordt. - - push bc - ld a,(number_pages) - ld b,a - ld a,(next_page) - cp b - pop bc - jr z,read_disk - - Hier wordt gekeken of er nog wel plek in het geheugen is om - de sector te cachen. Als dat niet zo is, wordt naar - 'read_disk' gesprongen waar de sectoren direct van diskette - worden gelezen. Let op: HL staat nog op de stack! Dit is zo - gedaan omdat HL nu nog eventjes nodig is. Lees maar eens - verder... - - ld (hl),a ; save current cache-page - - ld a,(next_address) - inc hl - ld (hl),a ; store hi-byte cache- - address - - De mapper-page en het adres waar de sector moet komen te - staan in het "cache-geheugen" worden opgeslagen. - - push bc - push de - ld d,b - ld e,c - ld c,setdta - call bdos ;set read address - pop de - pop bc - pop hl ; drive + number of sectors - back from stack - - Hier wordt het Disk Transfer Address goed gezet. - - push bc - push de - push hl - push bc ;destinationaddress - ld h,1 - ld c,diskrd - call bdos ;read 1 sector - - Een sector wordt ingelezen. - - in a,(#fd) - pop hl - push af - push hl - - ld a,(next_page) - out (#fd),a - - ld a,(#f342) - ld h,#40 - call enaslt - - Er wordt RAM geselecteerd op #4000-#7fff en de juiste page - wordt ingesteld. - - ld a,(next_address) - ld d,a - ld e,0 - pop hl ;Home Location - ld bc,512 - ldir ;move it to cache-memory - - De sector wordt naar het cache-geheugen verplaatst... - - ld a,(#fcc1) - ld h,#40 - call enaslt - - pop af - out (#fd),a - pop hl - pop de - pop bc - - call change_pointer ;change cache-pointer - - jp read_sectorslp ;repeat for next sector - - .. en de geheugeninstellingen worden weer hersteld. - Vervolgens wordt de routine change_pointer aangeroepen waar - het volgende adres voor de sector wordt veranderd en - eventueel de volgende pagina. Tot slot wordt gesprongen naar - read_sectorslp waar gekeken wordt of er nog meer sectoren - zijn om te lezen. - - change_pointer:ld a,(next_address) - inc a - inc a - ld (next_address),a ;next 512 bytes - cp #80 ;does it fit in the same page? - ret nz ;Yes -> finished here - ld a,#40 ;Begin of mapperpage (#4000) - ld (next_address),a - ld a,(next_page) - inc a - ld (next_page),a ;Next mapperpage for - caching - ret - - Het volgende adres in het cache-geheugen wordt berekend. Als - het adres #8000 wordt, wordt het adres weer op #4000 gezet - en wordt de volgende pagina met ��n verhoogd. - - ; read sector from disk - read_disk1: push hl ;number of sectors+drive has - to be pushed - read_disk: push de - - ld d,b - ld e,c - ld c,setdta - call bdos ;set read address - - pop de - pop hl ;number of sectors+drive back - from stack - ld c,diskrd - call bdos ;read rest of the sectors from - disk - ret - - Deze routine leest de resterende sectoren van diskette. Naar - read_disk1 wordt gesprongen als er bij het initialiseren van - de cache-routine's gebleken is dat er �berhaupt te weinig - geheugen voor caching is en naar read_disk wordt gesprongen - als er geen cache-geheugen meer over is. - - ; Move sector from cache-memory to destination address - ; In: HL: pointer to position-information - ; BC: destination address - ; DE: number of sectors - ; Note: number of sectors to be read and drive are pushed on the - ; stack (HL) - read_cache: push bc - push de - - push bc - push de - push hl - - ld a,(#f342) - ld h,#40 - call #24 - - pop hl - pop de - pop bc - - in a,(#fd) - push af - - ld a,(hl) - out (#fd),a - - Deze routine leest een sector vanuit het cache-geheugen. - Eerst wordt het juiste geheugen geschakeld.. - - inc hl - ld h,(hl) - ld l,0 - ld d,b - ld e,c - ld bc,512 - ldir - - ..vervolgens wordt de sector verplaatst.. - - ld a,(#fcc1) - ld h,#40 - call #24 - - pop af - out (#fd),a - - pop de - pop bc - pop hl - - ..en tot slot worden de geheugeninstellingen weer hersteld. - - read_sectorslp:dec h - ret z - - inc de - - inc b - inc b - jp read_sectors - - Het aantal sectoren wordt verlaagd, de te lezen sector wordt - verhoogd en het bestemmingsadres wordt met 512 verhoogd. - - number_pages: defb 0 - - next_page: defb 8 - next_address: defb #40 - - cache_table: defs 1440 * 2 - - Tot slot volgen het aantal ram-pages, de volgende pagina en - het volgende adres voor het cachen van sectoren en als - allerlaatste is er de tabel waarin staat of de sectoren - gecached zijn en waar ze dan gecached zijn. - - Nog een leuk nieuwtje: Smael gaat binnenkort proberen om een - cache-routine in de FD-routines te implementeren, als er nog - genoeg ruimte voor is. Ikzelf zie het nut er niet van in, - maar ja, als hij het zo graag wil...(NvdR: laat die jongen - toch, hij weet niet beter). Maar goed, het zit er weer op - voor deze keer. Tot de volgende FD! - - -Arjan diff --git a/Sunrise Special/1/Disk cursus special 1.md b/Sunrise Special/1/Disk cursus special 1.md deleted file mode 100644 index c7f76e0..0000000 --- a/Sunrise Special/1/Disk cursus special 1.md +++ /dev/null @@ -1,647 +0,0 @@ -# D I S K C U R S U S S P E C I A L ( 1 ) - - -## I N L E I D I N G - -In de diskcursus op Sunrise Magazine had ik al aangekondigd -dat er op de Sunrise Special een diskcursus voor gevorderden -zou komen. De cursus op het magazine is voornamelijk op -BASIC gericht, terwijl we hier juist de machinetaal aspecten -van het diskgebruik gaan bespreken. Ik ga er hier vanuit dat -de lezer een behoorlijke basiskennis heeft, ik zal dan ook -niet meer gaan uitleggen wat bijvoorbeeld een file is. - -Veel programmeurs vinden diskgebruik in machinetaal -moeilijk. Toch is het tamelijk eenvoudig, mits men in het -bezit is van duidelijke uitleg en documentatie. Elke MSX -computer met diskdrive heeft namelijk dezelfde serie BDOS -system calls tot zijn beschikking, waarmee vrijwel al het -werk uit handen wordt genomen. - -In deze cursus op de Special zullen (onder voorbehoud) de -volgende onderwerpen aan bod komen: - -- BDOS system calls -- BIOS calls (PHYDIO en FORMAT) -- Opbouw en werking bootsector -- Opbouw en werking FAT -- Opbouw en werking directory -- Zelf een programma schrijven dat vanuit de bootsector -opstart -- Zelf .COM files schrijven - -Dit is alles voor MSX-DOS 1/Disk BASIC 1.0. Misschien dat ik -aan het eind van de cursus verder ga met MSX-DOS 2/Disk -BASIC 2.01, maar dat is nu nog niet zeker. - -In dit eerste deel de werking van FAT en directory, oftewel -hoe staan files op een disk. - -## F A T - -Meteen al een ingewikkeld onderwerp: de File Allocation -Table. Bij het MSX Disk Operating System (kortweg MSX-DOS) -worden files behandeld als een verzameling clusters. Een -cluster bestaat bij een normale MSX disk (3.5") uit twee -sectoren. Een cluster is dus 2 * 512 = 1024 bytes (1 kB) -groot. - -Een file beslaat altijd minimaal ��n cluster, maar een file -die groter is dan ��n cluster worden over meerdere clusters -verdeeld. Dit betekent dat een file van slechts 1 byte op de -diskette toch maar liefst 1024 bytes in beslag neemt (1 -cluster), en een file van 2049 bytes 3 clusters (met in het -derde cluster slechts 1 byte). - -De FAT zorgt ervoor dat de ruimte op de disk altijd optimaal -wordt benut. Als er vaak op een diskette files worden -toegevoegd en andere files gewist, zullen de "volle" -clusters niet meer aaneengesloten op de disk staan. Zonder -de FAT zouden deze "gaten" niet meer kunnen worden benut. - -Als op een diskette waarop de vrije ruimte niet aan een -gesloten is een (grote) file wordt gezet, dan zullen eerst -de vrije ruimtes worden opgevuld, pas daarna wordt de vrije -ruimte "achteraan" benut. Zonder de FAT zou deze file later -nooit meer in te laden zijn, omdat het niet bekend is waar -de file verder gaat. In de FAT wordt dit bijgehouden. - -Stel u heeft de volgende files achter elkaar op een disk -staan: - -SUNRISE.001 cluster 2 t/m 4 -SUNRISE.002 cluster 5 t/m 6 -SUNRISE.003 cluster 7 t/m 10 - -Nu geeft u een KILL"SUNRISE.002" opdracht. De volgende -situatie ontstaat: - -SUNRISE.001 cluster 2 t/m 4 -vrij cluster 5 t/m 6 -SUNRISE.003 cluster 7 t/m 10 - -Nu zet u de file "SUNRISE.004" op de disk, die acht clusters -groot is. Nu gebeurt het volgende: - -SUNRISE.001 cluster 2 t/m 4 -SUNRISE.004 cluster 5 t/m 6 en 11 t/m 16 -SUNRISE.003 cluster 7 t/m 10 - -De file "SUNRISE.004" staat nu niet meer aaneengesloten op -de disk. Toch zal MSX-DOS de file zonder enig probleem -inlezen. En dat is waar de FAT om de hoek komt kijken. In -deze File Allocation Table (de naam zegt het al), wordt -namelijk opgeslagen waar (met welke cluster) een file verder -gaat. - - -## D E S T R U C T U U R - -De eerste byte van de FAT is de "FAT ID" byte. Dit is de -gewoon de "media ID", waarmee het formaat diskette wordt -aangegeven. Deze informatie staat ook in de bootsector, maar -het is natuurlijk makkelijk dat het ook in de FAT staat, -zodat de bootsector niet bij elke diskactie hoeft te worden -ingelezen. Bij MSX zijn de volgende twee ID's gebruikelijk: - -Naam: Aantal zijden: ID: - -MF-1DD 1 &HF8 -MF-2DD 2 &HF9 - -De volgende twee bytes van de fat zijn altijd &HFF en doen -niet ter zake. Op de vierde byte begint de eigenlijke tabel. -De informatie is opgeslagen in een vreemd formaat van 12 -bits per FAT entry. De eerste FAT entry is nummer 2. Het -nummer van de FAT entry is ook het nummer van de cluster die -ermee correspondeert. Een voorbeeld FAT in hexadecimaal: - -F9 FF FF 03 40 00 FF 6F 00 FF .F .. .. .. -0 1 2 3 4 5 6 7 8 9 10 11 -------- ------- -------- -entry entry entry -2 en 3 4 en 5 6 en 7 - -De bytes 0 t/m 2 bevatten de FAT ID (F9) en twee dummy bytes -(FF FF), het betreft hier een dubbelzijdige diskette. De -bytes 3 t/m 5 bevatten de informatie van cluster 2 en 3. Dit -moet als volgt worden gelezen: - -waarde cluster 2 = RECHTER nibble byte 4 + byte 3 = 003 -waarde cluster 3 = byte 5 + LINKER nibble byte 4 = 004 - -De waarde in een FAT entry wijst naar de cluster waarin de -file verder gaat. In FAT entry 2 staat "003", dus de file -gaat verder in cluster 3. In FAT entry 3 staat "004", dus de -file gaat verder in cluster 4. Zo eenvoudig is dat! - -Het einde van een file wordt aangegeven met "FFF". In fat -entry 4 staat "FFF", dus daar eindigt de file. De file staat -dus op cluster 2 t/m 4. We herhalen het stukje FAT nogmaals: - -F9 FF FF 03 40 00 FF 6F 00 FF .F .. .. .. -0 1 2 3 4 5 6 7 8 9 10 11 -------- ------- -------- -entry entry entry -2 en 3 4 en 5 6 en 7 - -We zien dat FAT entry 5 de waarde 006 bevat, de file gaat -dus verder met cluster 6. In FAT entry 6 staat FFF, dus daar -eindigt de file. Dit is dus een korte file, die slechts twee -clusters beslaat (5 en 6). - -Omdat de volgorde van de bytes nogal vreemd is zal ik nog -een duidelijk voorbeeld geven: - -21 43 65 - -Deze FAT entry's bevatten respectievelijk &H321 en &H654. - -Een leeg cluster wordt aangegeven met "000". Indien u een -bepaald gedeelte van een diskette wilt beschermen tegen de -BDOS (omdat u daar zelf de disk rechtstreeks op sector -niveau wilt lezen/schrijven), kunt u het overeenkomstige -deel van de FAT vullen met FFF. - - -## P L A A T S V A N D E F A T - -De FAT staat direct na de bootsector, en begint dus op -sector 1. Het aantal sectoren dat de FAT in beslag neemt is -afhankelijk van de grootte van de diskette. De grootte van -de FAT staat in de bootsector. Bij MSX-DOS wordt er direct -achter de FAT ook nog een kopie van de FAT bewaard. (In de -bootsector staat ook het aantal FATs vermeld.) Deze kopie is -nodig omdat de diskette niet meer normaal te gebruiken is -als de FAT niet meer in orde is. - -Rekent u even mee? Een dubbelzijdige diskette heeft 713 -clusters (7 clusters = 14 sectoren zijn nodig voor -bootsector (1), 2 FATs (6) en directory (7).) De FAT heeft -aan het begin ook nog twee clusters met de FAT-ID, dus in -totaal zijn er 715 FAT entry's. Elke entry vergt 12 bits, -dus er zijn 8.580 bits nodig. Een sector telt 4096 bits, dus -op een dubbelzijdige diskette neemt de FAT 3 sectoren in -beslag. De FAT staat dus op sector 1 t/m 3 en de reserve FAT -op sector 4 t/m 6. - -Bij een enkelzijdige diskette zijn twee sectoren -noodzakelijk, en staat de FAT dus op sector 1 en 2 en de -reserve FAT op sector 3 en 4. - - -## D I R E C T O R Y - -Met alleen de FAT kom je er niet. Je kunt een file immers -niet terugvinden zonder te weten waar hij begint (het nummer -van de eerste cluster). Dus staat er op een diskette direkt -achter de FAT (dubbelzijdig sector 7 t/m 13, enkelzijdig -sector 5 t/m 11) de directory (inhoudsopgave). In de -directory worden de volgende gegevens opgeslagen: - -- de filenaam -- de extensie -- de tijd -- de datum -- de lengte -- de eerste cluster - -De directory is 7 sectoren lang, dat is 3584 bytes. Elke -directory entry vergt 32 bytes, er passen dus 112 files op -een diskette. Maar dat wist u natuurlijk al. - - -## D E S T R U C T U U R - -Hoe is de directory opgebouwd? De 112 entry's staan achter -elkaar op de zeven sectoren. Elke entry is 32 bytes lang. -Deze bytes zijn als volgt ingedeeld: - -+0 Filenaam -+8 Extensie -+11 Attribuut -+12-21 Niet gebruikt (voor compatibility met MS-DOS) -+22 Tijd -+24 Datum -+26 Eerste cluster -+28 File lengte - -Voor de filenaam en de extensie verwijs ik u naar Disk -Cursus (1) op Sunrise Magazine #1. De Filenaam is maximaal 8 -karakters lang, de extensie maximaal 3 tekens. De punt staat -uiteraard niet in de directory. - -De attribuut wordt bij MSX-DOS1 eigenlijk niet gebruikt, -normaal staat daar een 0. Bij MSX-DOS2 (en MS-DOS) worden -hier de attributen (read only, hidden, etc.) bewaard. De -enige attribuut die door MSX-DOS1 wordt "ondersteund" is -"hidden", de file is dan helemaal niet meer in te lezen en -komt niet in de filelist voor als die wordt opgevraagd met -DIR of FILES. Onder MSX-DOS1 is de attribuut byte als volgt -opgebouwd: -``` -MSB 7 6 5 4 3 2 1 0 LSB - x x x x x x H x -``` -x: niet gebruikt -H: 1=hidden, 0=normaal - -De tijd is opgeslagen in twee bytes: -``` -MSB 7 6 5 4 3 2 1 0 LSB -U4 U3 U2 U1 U0 M5 M4 M3 Byte 23 -M2 M1 M0 S4 S3 S2 S1 S0 Byte 22 -``` -U0-U4: uren (0-23) -M5-M0: minuten (0-59) -S4-S0: secondes (0-29) - -Waarbij de secondes door 2 zijn gedeeld (om het goede getal -te krijgen moet de waarde die in S0-S4 is opgeslagen dus met -2 worden vermenigvuldigd). Let op de volgorde van de bytes! - -De datum is op soortgelijke wijze opgeslagen: -``` -MSB 7 6 5 4 3 2 1 0 LSB -J6 J5 J4 J3 J2 J1 J0 M3 Byte 25 -M2 M1 M0 D4 D3 D2 D1 D0 Byte 24 -``` -J0-J6: jaar (1980-2079, moet 1980 bij worden opgeteld) -M0-M3: maand (1-12) -D0-D4: dag (1-31) - -Let wederom op de volgorde van de bytes! - -De eerste cluster en de filelengte staan in normaal Z80 -formaat, dus de bytes in volgorde van low naar high: - -cluster = (byte 26) + 256 * (byte 27) -filelengte = (byte 28) + 256 * (byte 29) + 65536 * (byte 30) -+ 16777216 * (byte 31) - -Byte 31 van de filelengte zal bij een normale diskette niet -worden gebruikt, omdat de maximale lengte van een file (op -een dubbelzijdige diskette) 713 * 1024 = 730.112 bytes -bedraagt. Daarvoor zijn drie bytes (0-16.777.215, 16 MB) -ruimschoots voldoende. De vierde byte (waardoor waardes tot -256^4 mogelijk zijn, 4096 MB), wordt alleen bij harddisks -gebruikt. - -Als een nieuwe file op een disk wordt gezet, wordt daarvoor -de eerste de beste vrije directory entry gebruikt. Als een -file wordt gewist, wordt de eerste byte van de filenaam -vervangen door &HE5. Een 0 als eerste byte van de filenaam -geeft aan dat deze en alle volgende entry's nog nooit zijn -gebruikt en dus leeg zijn. - -Als de directory vol is, kunnen er geen nieuwe files meer op -de disk worden gezet. Ook niet als er nog bergen vrije -clusters zijn. Bij MSX-DOS2 is dit probleem opgelost door -subdirectories, maar bij DOS1 zullen we gewoon een nieuwe -disk moeten pakken of een paar oude files moeten killen. - -## E E N V O O R B E E L D - -Op deze Sunrise Special #1 staat het BASIC programma -"DIR.BAS". Dit programma past de eerder verworven kennis -toe. Dit programma geeft van een diskette een zeer volledige -directory, met de volgende gegevens: - -- de filenaam -- de tijd -- de datum -- de filelengte in bytes -- de filelengte in clusters (cls) -- een lijstje met alle clusters waarop de file staat in de -juiste volgorde - -De eerste vier worden ook door het DIR commando van MSX-DOS -gegeven, en daarvoor hoeft alleen de directory worden -uitgelezen. Maar voor het laatste moet de FAT worden -uitgeplozen. - -Ik heb het programma in BASIC geschreven omdat het dan -makkelijker is te volgen, bovendien zou ik bij machinetaal -dingen moeten gebruiken die we nu nog niet gehad hebben. -Hieronder volgt de listing, die ook in het softwaremenu te -vinden is. De listing wordt regelmatig onderbroken voor -uitleg. - - -## D I R . B A S -``` -1000 'DIR.BAS -1010 'Door Stefan Boer -1020 'Geeft dir met filenaam, tijd, datum, lengte, aantal -clusters en clusterverdeling van file -1030 'Voor Sunrise Special #1 - Bij Disk Cursus Special (1) -1040 '(c) SteveSoft/Stichting Sunrise 1992 -1050 ' -1060 CLEAR200,&HBFFF:DEFINTA-Z:DEFUSR=&H156 -``` -In regel 1060 wordt het gebied vanaf &HC000 tegen BASIC -beschremd, hier komen de FAT en de directory te staan. De -BIOS routine op adres &H156 wist de toetsenbordbuffer, met -DEFINTA-Z wordt bepaald dat alle variabelen integers zijn. -``` -1070 DEFFNA$(X)=RIGHT$("0"+MID$(STR$(X),2),2) -1080 KEYOFF:SCREEN0:WIDTH80:COLOR=(4,0,0,4):COLOR15,4,4 -1090 PRINT"Uitgebreide directory" -1100 PRINT"Door Stefan Boer" -1110 PRINT"Gepubliceerd op Sunrise Special #1" -1120 PRINT"(c) Stichting Sunrise 1992" -``` -In regel 170 wordt een functie gedefinieerd, die nodig is -voor een nette datum en tijd. De functie voegt waar nodig -"verloopnullen" toe, zodat je bijvoorbeeld 01/06/1992 -krijgt. -``` -1130 PRINT -1140 PRINT"Plaats een diskette...";:U=USR(0):I$=INPUT$(1) -1150 PRINT:PRINT:PRINT"Inlezen van FAT en directory..." -1160 POKE&HF351,0:POKE&HF352,&HC0:A$=DSKI$(0,1): -POKE&HF352,&HC2:A$=DSKI$(0,2) -``` -In regel 1160 worden de eerste twee sectoren van de FAT -gelezen en vanaf &HC000 in het RAM gezet. Door het commando -A$=DSKI$(drive,sector) komt er niets in de variabele A$ -terecht (dat kan ook niet, want een string kan maar 255 -tekens lang zijn, en geen 512). De inhoud van de sector -wordt in het geheugen geplaatst, en wel vanaf het adres dat -op locatie &HF351/&HF352 staat. Drive 0 betekent de default -drive. -``` -1170 IFPEEK(&HC000)=&HF9THENS=7:POKE&HF352,&HC4: -A$=DSKI$(0,3)ELSES=5 -1180 FORI=0TO6:POKE&HF352,&HC6+2*I:A$=DSKI$(0,S+I):NEXT -``` -In regel 1170 wordt de FAT ID byte gelezen. Hieraan is te -zien of de diskette enkelzijdig (&HF8) is, of dubbelzijdig -(&HF9). Is de diskette dubbelzijdig, dan bestaat de FAT uit -drie sectoren (de derde sector wordt ingeladen) en begint de -directory op sector 7 (S=7), bij een enkelzijdige diskette -bestaat de FAT uit twee sectoren (die reeds zijn ingelezen), -en begint de directory op sector 5 (S=5). - -In regel 1180 wordt de directory ingelezen, die 7 sectoren -lang is. De directory wordt vanaf &HC600 in het RAM gezet. -``` -1190 PRINT:PRINT"Filenaam: Datum: Tijd: Bytes: -Cls: Clusters:":PRINT -``` -"Cls" staat voor de lengte in clusters, "Bytes" voor de -lengte in bytes. Onder "Clusters:" komen de clusters waarop -de file staat in de juiste volgorde te staan. -``` -1200 FORAD=&HC600TO&HD3FFSTEP32 -1210 IFPEEK(AD)=0THENENDELSEIFPEEK(AD)=&HE5THEN1360 -``` -Regel 1200 doorloopt de complete directory in het RAM. Die -directory begint op &HC600 en is 3.5 kB lang. Een directory -entry is 32 bytes groot. In regel 1210 wordt gekeken of het -einde van de directory is bereikt (eerste byte van filenaam -is 0), zo ja, dan wordt het programma met END be�indigt. Is -de eerste byte &HE5, dan is de file gewist en wordt er -verder gegaan met de volgende file (op regel 1360 staat een -NEXT commando). - -1220 FORI=0TO7:PRINTCHR$(PEEK(AD+I));:NEXT -1230 IFPEEK(AD+8)=32THENPRINT" ";ELSEPRINT".";: -FORI=8TO10:PRINTCHR$(PEEK(AD+I));:NEXT:PRINT" "; - -Deze twee regels zetten de filenaam op het scherm. Regel -1230 zet alleen een punt op het scherm indien er een -extensie is. -``` -1240 PRINTFNA$(PEEK(AD+24)AND31);"/";FNA$((PEEK(AD+24) -AND224)\32+8*(PEEK(AD+25)AND1));"/";:PRINTUSING -"#### ";PEEK(AD+25)\2+1980; -``` -Regel 1240 zet de datum op het scherm, die in de bytes 24 en -25 van de directory entry staat. Met de ingewikkelde -formules worden de juiste bits uit de twee bytes gefilterd. -De dag staat bijvoorbeeld in bit 0 t/m 4 van byte 24. Met -een AND 31 (=&B11111) instruktie wordt de dag uit de byte -gehaald. Ter herinnering: -``` -MSB 7 6 5 4 3 2 1 0 LSB -J6 J5 J4 J3 J2 J1 J0 M3 Byte 25 -M2 M1 M0 D4 D3 D2 D1 D0 Byte 24 -``` -``` -1250 PRINTFNA$(PEEK(AD+23)\8);":";FNA$((PEEK(AD+23)AND7)*8+ -(PEEK(AD+22)AND224)\32);":";FNA$(2*(PEEK(AD+22)AND31)); -" "; -``` -Met de tijd gaat het net zo. Het schema van de tijd opslag -nog een keer: -``` -MSB 7 6 5 4 3 2 1 0 LSB -U4 U3 U2 U1 U0 M5 M4 M3 Byte 23 -M2 M1 M0 S4 S3 S2 S1 S0 Byte 22 -``` -``` -1260 L#=PEEK(AD+28)+256*PEEK(AD+29)+65536!*PEEK(AD+30): -PRINTUSING"###### ";L#; -``` -Hier wordt de lengte in bytes uit de directory gelezen en op -het scherm gezet. Eigenlijk moet ook AD+31 worden -uitgelezen, maar die wordt bij een diskette toch niet -gebruikt. Er moet een # achter de L, omdat een file groter -kan zijn dan 32767 bytes, en dan zou je zonder # een -"Overflow" foutmelding krijgen (vanwege de DEFINTA-Z). -``` -1270 PRINTUSING"### ";INT((L#+1023)/1024);:X=45 -``` -Hier wordt het aantal clusters dat de file in beslag neemt -berekend en op het scherm gezet. De berekening zou ook -als volgt kunnen worden gedaan: -``` -CL=INT(L#/1024):IFCL<>L#/1024THENCL=CL+1 -``` -Het resultaat is precies hetzelfde (CL is het aantal -clusters), maar ik vind de eerste manier veel mooier. -INT(L#/1024) is niet goed, omdat je dan bijna altijd 1 -cluster te weinig hebt (INT(1000/1024) is 0, maar een file -van 1000 bytes neemt ��n cluster in beslag). INT(L#/1024)+1 -is meestal goed, maar niet als L# een veelvoud van 1024 is -(zoals in de tweede oplossing duidelijk is te zien). -``` -1280 C=PEEK(AD+26)+256*PEEK(AD+27) -``` -Lees het nummer van de eerste cluster uit de directory. Dit -staat op byte 26 en 27. -``` -1290 FA=(CAND1022)*1.5+&HC000:PRINTTAB(X);: -PRINTUSING"###";C;:X=X+4:IFX=81THENX=45 -``` -In regel 1290 wordt het FAT adres (FA) berekend. C AND 1022 -zorgt dat C een even getal wordt, door er 1 vanaf te trekken -als het oneven was. Omdat twee FAT entry's samen 3 bytes in -beslag nemen, wordt dit vermenigvuldigd met 1.5. &HC000 is -het startadres van de FAT in het RAM. - -In X wordt de actuele X-coordinaat van de cursor -bijgehouden, zodat de clusternummers netjes rechts van de -overige informatie komen te staan. Het clusternummer wordt -op het scherm gezet met een PRINT USING, en de nieuwe X -coordinaat wordt berekend. -``` -1300 IFC<>(CAND1022)THEN1340 -``` -In deze regel wordt gekeken of we de eerste (even -clusternummer) of de tweede (oneven clusternummer) FAT entry -uit het groepje van 3 bytes moeten hebben. In regel 1310 -wordt de even gelezen, in regel 1340 de oneven. -``` -1310 V=C:C=(PEEK(FA+1)AND15)*256+PEEK(FA) -1320 IFC=&HFFFTHEN1370ELSEIFV<>C-1THENPRINTTAB(X-1);">"; -1330 GOTO1290 -``` -Hier wordt de even FAT entry gelezen. De 4 hoogste bits -staan op FA+1 en de 8 laagste bits op FA. Deze waarde wijst -naar de volgende cluster. Als de waarde gelijk is aan &HFFF -dan is het einde van de file bereikt, en wordt verder gegaan -met de volgende file (regel 1370). Anders wordt er -teruggegaan naar regel 1290, waar het nieuwe FAT adres wordt -berekend, het clusternummer wordt geprint en weer verder -wordt gegaan met het uitlezen van die FAT entry. In V wordt -het Vorige clusternummer bewaard, in regel 1320 wordt -gekeken of dat ��n lager is dan het zojuist berekende -clusternummer (als dat zo is, dan zijn het twee opeen -volgende clusters). Er wordt een > op het scherm gezet als -er een "gat" is. -``` -1340 V=C:C=((PEEK(FA+1)AND240)\16)+PEEK(FA+2)*16 -1350 IFC=&HFFFTHEN1370ELSEIFV<>C-1THENPRINTTAB(X-1);">"; -1360 GOTO1290 -``` -In regel 1340 t/m 1360 precies hetzelfde, alleen nu voor de -FAT entry met een oneven nummer. Hier staan de 4 laagste -bits op FA+1 en de 8 hoogste bits op FA+2. -``` -1370 IFPOS(0)>0THENPRINT -1380 NEXT -``` -Regel 1370 zorgt ervoor dat er op een nieuwe regel wordt -begonnen. Als er alleen PRINT zou hebben gestaan, zou er een -regel over worden geslagen als de cursor al op een nieuwe -regel stond. Regel 1380 zorgt dat er met de volgende -directory entry wordt verdergegaan. - - -## V O O R B E E L D U I T V O E R - -Laten we een eerder gebruikt voorbeeld nog eens nemen. Op -een disk staan de files: - -SUNRISE.001 cluster 2 t/m 4 -SUNRISE.004 cluster 5 t/m 6 en 11 t/m 16 -SUNRISE.003 cluster 7 t/m 10 - -DIR.BAS geeft dan de volgende uitvoer: - -Filenaam: Datum: Tijd: Bytes: Cls: Clusters: - -SUNRISE .001 22/06/1992 16:03:42 2404 3 2 3 4 -SUNRISE .004 24/06/1992 10:12:02 7169 8 5 6> 11 - 12 13 14 - 15 16 -SUNRISE .003 22/06/1992 16:10:16 3092 4 7 8 9 - 10 - -Het ">" tekentje geeft dus aan dat er een sprong wordt -gemaakt. Het kan soms voorkomen dat het programma de soep in -loopt. Dit ligt dan niet aan DIR.BAS (hoop ik), maar dan is -er waarschijnlijk iets mis met de FAT van die diskette. - -Gebruikt u DIR.BAS en ziet u veel > tekentjes, dan is het -verstandig om die diskette met een kopieerprogramma op -bestandsniveau (bijvoorbeeld BK of gewoon COPY onder -MSX-DOS) naar een andere (lege!) diskette te kopi�ren. De -bestanden worden dan weer netjes aangesloten achter elkaar -gezet. Bij het laden van een file betekent elk > tekentje -namelijk dat er een stuk van de disk moet worden -overgeslagen, en dit kost meestal extra tijd. Let op: -kopi�ren met een kopieerprogramma op sectorniveau (XCopy, -FastCopy, WorkMate, TurboCopy, etc.) heeft hier geen zin, -omdat de diskette dan letterlijk wordt overgenomen. - - -## B D O S - -Dit is behoorlijk ingewikkeld, maar gelukkig hoeft de -machinetaalprogrammeur zich normaal gesproken niet druk te -maken over FAT en directory. Als alle diskacties via de BDOS -worden afgehandeld (die in een volgend deel van de cursus -zeer uitgebreid zal worden besproken), dan zorgt de BDOS -ervoor dat de FAT en directory keurig worden bijgehouden. - -Toch is het handig om van deze informatie op de hoogte te -zijn. Het is bijvoorbeeld best te doen om een supersnel -laadsysteem te schrijven, waarbij de directory en de FAT in -het geheugen staan. Die hoeven dan niet steeds te worden -ingeladen, zodat de kop van de diskdrive minder op en neer -hoeft te gaan. Dit versnelt het laden van files aanzienlijk. -Dit systeem wordt toegepast bij BK, de BestandsKopieerder -voor MemMan van MCM's MST. - - -## W A A R S C H U W I N G ! ! - -Dit is een zeer belangrijke waarschuwing die ik ook nog wel -eens op Sunrise Magazine zal zetten. Stel er gebeurt het -volgende: - -U bent met een origineel programma bezig waarbij de diskette -waarop dat originele programma staat uiteraard op write -protected staat. Nu wilt u iets saven op een werkdisk, dus u -kiest de save optie. Maar per ongeluk laat u de disk van het -originele programma in de drive zitten, waardoor er een -write protected foutmelding volgt. U kunt kiezen uit Retry -of Abort. - -De logische oplossing lijkt nu om de werkdisk in de drive te -doen (write enable) en voor retry te kiezen. - -## D O E D I T N O O I T ! ! ! - -U kunt uw werkdisk daarna wel formatteren, want in ieder -geval de FAT en meestal ook de directory zal compleet -vernield zijn!!! - -Dit is een foutje van de BDOS, die in zo'n geval niet eerst -de FAT en directory van de nieuwe disk inlaadt, maar er -vanuit gaat dat alleen de write protect eraf is gehaald en -dat het nog steeds dezelfde diskette is. De BDOS maakt dus -de nodige wijzigingen in de FAT en directory die hij nog in -het RAM had staan en schrijft die dan naar de disk. Dat -waren dus de FAT en directory van de disk met het originele -programma, en die worden nu op uw werkdisk geschreven. U -begrijpt wel dat de informatie die op die werkdisk stond -alleen met zeer veel moeite of helemaal niet is terug te -halen. Kortom, kies in zo'n geval altijd voor abort en begin -opnieuw met het saven. Dan zal het wel goed gaan. - -Ik denk dat veel MSX'ers al eens een dergelijke ramp hebben -meegemaakt (bij mij is m'n disk met teksten al een stuk of -vijf keer op deze manier naar de haaien gegaan voordat ik -doorhad hoe het kwam), en niet wisten waar het aan lag. Nu -weet u het wel, en het kan u een hoop werk en ergernis -besparen! - -Oproep aan iedereen die software uitgeeft: waarschuw -hiervoor in de handleiding of maak een retry onmogelijk. (Ik -zal hier bij alle software die Sunrise uitgeeft persoonlijk -op letten!) - - -## T O T S L O T - -Ik denk dat ik er na deze afdwaling maar een eind aan draai. -Ik weet nu nog niet wat ik de volgende keer ga doen, maar -dat zou best wel eens de BDOS kunnen zijn. Dat zal een hele -lange tekst worden, want er zijn 42 BDOS calls! Tot de -volgende keer! - -Stefan Boer diff --git a/Sunrise Special/1/Geheugen tellen.md b/Sunrise Special/1/Geheugen tellen.md deleted file mode 100644 index 4b6bcba..0000000 --- a/Sunrise Special/1/Geheugen tellen.md +++ /dev/null @@ -1,312 +0,0 @@ -# G E H E U G E N T E L L E N - - -Niet elke MSX computer heeft dezelfde hoeveelheid RAM -geheugen. Vandaar dat het soms handig is om even te kijken -hoeveel geheugen er aanwezig is, zodat het lopende programma -daar rekening mee kan houden. - -Dit wordt bijvoorbeeld ook gedaan door de layoutroutine van -de Sunrise Special. Er wordt gekeken hoeveel RAM geheugen er -aanwezig is. Is dat 64 kB (het minimum op MSX2 en hoger), -dan moet elk MoonBlaster muziekje afzonderlijk worden -ingeladen. Is het meer, dan worden er zoveel mogelijk -MoonBlaster muziekjes in het geheugen gezet. Met 128 kB zal -er meestal al niet meer hoeven worden bijgeladen. - - -## A D D E R T J E - -Er zit echter een addertje onder het gras. Veel programmeurs -vinden het blijkbaar nogal moeilijk om zo'n routine te -schrijven. In demo's zit soms een hardwaretest, die ook -aangeeft hoeveel geheugen er aanwezig is. Ik heb het al heel -vaak meegemaakt dat zo'n routine veel te veel geheugen -opgeeft. Sommige demo's zeggen dat ik 2048 kB heb! Dat is -natuurlijk leuk, maar ik heb maar 256 kB dus heb ik er niets -aan als zo'n demo dat zegt. - - -## M E M O R Y M A P P E R - -De routine die ik geschreven heb, telt het RAM geheugen in -de huidige memorymapper dat op page 2 (&H8000-&HBFFF) is -geschakeld. De routine vindt dus niet AL het geheugen, -normaal gesproken alleen het geheugen van de grootste -mapper. Maar aangezien het gelijktijdig aansturen van -verschillende mappers een vervelende klus is, is het toch -niet zo erg. Ik raad u aan MemMan te gebruiken als u dat -toch van plan bent. - -Toch kan de routine wel gebruikt worden voor het tellen van -geheugen in verschillende mappers, er moet dan alleen een -routine omheen worden geschreven die alle sloten afgaat, -kijkt of er RAM in zit, ze op page 2 schakelt -(&H8000-&HBFFF) en vervolgens de telroutine aanroept. - -Dat schakelen van geheugen kan rechtstreeks gebeuren (met -I/O poort &HA8 en adres &HFFFF), of via de BIOS routine -ENASLT (&H0024). Misschien op de volgende Special de routine -die alle sloten afgaat. - -Bij het opstarten selecteert de MSX computer automatisch de -grootste mapper. Als in een Japanse MSX2+ met 64 kB dus een -externe mapper met 512 kB wordt gestoken, start de computer -vanuit die externe mapper op. Als u bijvoorbeeld een BASIC -programma laadt, dan komt dat in de externe mapper terecht. -Als u dus zonder eerst met het geheugen geknoeid te hebben -mijn routine gebruikt, zal altijd de grootte van de grootste -mapper worden bepaald. - - -## S L O T E N - -De plaats van het RAM in de computer is niet op alle -computers hetzelfde. Op de adressen &HF341 t/m &HF344 is per -page te vinden in welk slot het RAM zit: - -&HF341 page 0 &H0000-&H3FFF -&HF342 page 1 &H4000-&H7FFF -&HF343 page 2 &H8000-&HBFFF -&HF344 page 3 &HC000-&HFFFF - -De byte die op die adressen staat is een zogenaamde slot-ID -byte. Zo'n byte is als volgt opgebouwd: - -bit 7 6 5 4 3 2 1 0 - E 0 0 0 S1 S0 P1 P0 - -Bit 7 geeft aan of het slot geexpandeerd is of niet (1=ja). -Bits 2-3 geven het secundaire slotnummer (mits E=1). -Bits 0-1 geven het primaire slotnummer. - -De telroutine werkt vanuit page 2, dus daar moet de -memorymapper worden geschakeld. Normaal staat daar -natuurlijk al RAM, maar als dat niet zo is kan er op deze -manier RAM worden geschakeld: -``` - LD A,(&HF343) ; A=ID byte RAM page 2 - LD H,&H80 ; page 2 - CALL &H0024 ; ENASLT -``` -Voor de routine ENASLT moet de slot-ID byte in A staan, en -moet in HL een adres staan in de gewenste page. (Het is niet -nodig om LD HL,&H8000 te doen, want alleen de bovenste twee -bits van H worden hier gebruikt. Alle getallen tussen LD -H,&H80 en LD H,&HBF zijn dus geschikt.) U kan dit natuurlijk -ook zelf doen door met I/O poort &HA8 en adres &HFFFF aan de -gang te gaan, maar dat is veel ingewikkelder. Ik zal er hier -dan ook niet over uitweiden hoe dat in zijn werk gaat. - - -## S E G M E N T E N - -Er staat nu dus RAM op page 2. Dit RAM zit in een zogenaamde -memorymapper. Het RAM in een memorymapper is verdeeld in -blokken (soms wel 'maps' genoemd) van 16 kB. Ik noem deze -blokken verder segmenten. Per page is er een I/O poort -waarmee het segment van de memorymapper dat op die page -staat kan worden geselecteerd: - -page 0 &H0000-&H3FFF poort &HFC (3) -page 1 &H4000-&H7FFF poort &HFD (2) -page 2 &H8000-&HBFFF poort &HFE (1) -page 3 &HC000-&HFFFF poort &HFF (0) - -Tussen haakjes staan de standaardwaardes vermeld, zo is de -situatie als de computer is opgestart. Wees overigens niet -verbaasd als u andere waardes vindt bij het uitlezen van de -poorten, het gaat alleen om de geldige bits! - -Stel de computer heeft 64 kB, er zijn dan dus 4 segmenten -van 16 kB. Alleen de bits 0 en 1 van de vier poorten worden -dan gebruikt (zijn geldig), de overige 6 bits worden -genegeerd. (In twee bits kunnen namelijk vier verschillende -waardes worden gezet; 00, 01, 10 en 11.) - -Selecteer je bijvoorbeeld segment 9 op een computer met 128 -kB RAM (segmenten 0 t/m 7), dan wordt gewoon segment 1 -geselecteerd! (9 is &B1001, alleen de onderste drie bits -zijn geldig, &B001 is 1!) - -Een poort kan de waarde 0-255 bevatten, er kan totaal dus -256*16=4096 kB RAM in een memorymapper, oftewel 4 MB! - -Pas op met het gebruiken van segment 0, zoals je ziet staat -dit standaard op page 3, waar het systeem RAM staat. Zou je -dit segment ook op &HFE schakelen en het dan gebruiken, dan -zou het systeem RAM kunnen worden verminkt en slaat de -computer meestal vast. - -Voor poort &HFF geldt een zelfde waarschuwing, als je daar -een andere waarde naar schrijft moet je wel zorgen dat in -dat segment ook het systeem RAM staat, anders zal de -computer zeker hangen. - - -## T E L L E N - -Het bepalen van de grootte van de memorymapper is dus heel -simpel; gewoon het aantal segmenten tellen en dat -vermenigvuldigen met 16 kB. We gaan daarvoor alsvolgt te -werk: - -- We kiezen een adres uit wat zowel de routine als het - systeem RAM niet aantast -- We zetten in alle segmenten op dat adres een 0 -- We gaan nu alle segmenten langs en zetten daar een 255 als - we hem gehad hebben, zodat dubbel tellen uitgesloten is - -Deze procedure heeft een nadeel: na het doorlopen van de -routine is de inhoud van de memorymapper verminkt. Dit -kunnen we voorkomen door: - -- Aan het begin van de routine de waardes die op het gekozen - adres staan op te slaan in een buffer -- Aan het eind van de routine de waardes uit de buffer weer - terug te zetten - - -## D E S O U R C E - -Bovenstaande procedure is terug te vinden in de machinetaal- -routine die ik heb geschreven. Hier is de source, rijkelijk -voorzien van commentaar. - -``` -; M E M C O U N T . A S C -; Door Stefan Boer -; Deze routine telt het aantal aanwezige memorymaps -; op &H8000-&HBFFF -; Routine kan eventueel worden uitgebreid, zodat al het RAM -; wordt gevonden. -; 19/03/92, (c) SteveSoft 1992 -; Uitvoer: -; vanuit ML: A=hoogste memorymapper segment -; vanuit BASIC: U=USR(0) --> U=hoogste segment -; N.B. niet aantal segmenten, omdat 4 MB (256 segmenten) -; dan niet kan! - -; Enkele waardes - -ADRES: EQU &H81FF ; schrijft routine noch - ; systeem RAM over -MEMPRT: EQU &HFE ; I/O poort memorymapper - ; schakeling page 2 - - ORG &HC200 ; beginadres routine - -; Initialisatie - -MEMCNT: LD HL,ADRES ; HL check-adres - LD DE,BUFFER ; DE beginadres buffer - LD C,MEMPRT ; C I/O poort memorymapper - ; page 2 - IN A,(C) ; lees huidig segmentnummer - PUSH AF ; bewaar dit, wordt aan het - ; eind weer hersteld - -; Bewaar de huidige informatie die op +1FF staan -; N.B. Ik zeg +1FF in plaats van &H81FF omdat de segmenten -; geen vast beginadres hebben. Ze kunnen ook op 0000, -; 4000 of C000 staan. - - LD B,0 ; voer de lus 256 keer uit - ; (0 t/m 255) -SAVE: OUT (C),B ; schakel memorymapper - LD A,(HL) ; lees waarde +1FF - LD (DE),A ; zet waarde in buffer - INC DE ; volgende plaats in buffer - DJNZ SAVE ; doe dit met alle segmenten - ; (0 t/m 255) - -; Zet 0 op +1FF in alle segmenten - - LD B,0 ; voer de lus 256 keer uit - ; (0 t/m 255) - XOR A ; A=0 -ZERO: OUT (C),B ; schakel memorymapper - LD (HL),A ; zet 0 op +1FF - DJNZ ZERO ; doe dit met alle segmenten - ; (0 t/m 255) - -; Tel aantal werkelijk aanwezige segmenten - - LD D,0 ; D aantal gevonden segmenten - LD B,0 ; voer de lus 256 keer uit - ; (0 t/m 255) -CHECK: OUT (C),B ; schakel memorymapper - LD A,(HL) ; lees +1FF - CP &HFF ; al geteld? - JR Z,SLAOVR ; Ja, dan volgende segment - INC D ; aantal segmenten verhogen - LD (HL),&HFF ; segment gehad -SLAOVR: DJNZ CHECK ; doe dit met alle segmenten - ; (0 t/m 255) - PUSH DE ; bewaar aantal segmenten - -; Herstel de inhoud van +1FF van alle segmenten - - LD DE,BUFFER ; beginadres waar waardes - ; zijn opgeslagen - LD B,0 ; 256 segmenten (0 t/m 255) -RESTOR: OUT (C),B ; schakel memorymapper - LD A,(DE) ; lees waarde uit buffer - LD (HL),A ; zet waarde terug op oude - ; plaats - INC DE ; volgende plaats in buffer - DJNZ RESTOR ; doe dit met alle segmenten - ; (0 t/m 255) - -; Geef gevonden waarde door aan BASIC en ML en herstel -; originele stand van de memorymapper. - - POP DE ; D bevat aantal segmenten - POP AF ; haal oude waarde &HFE terug - OUT (C),A ; memorymapper page 2 weer - ; zoals bij begin - LD A,2 ; integer - LD (&HF663),A ; geef type variabele aan - ; BASIC door - LD A,D ; A bevat aantal segmenten - ; van 16 kB --> ML - DEC A ; met een verminderen - ; niet aantal maar hoogste! - LD L,A - LD H,0 ; LD HL,A - LD (&HF7F8),HL ; geef waarde aan BASIC door - RET ; einde routine - -BUFFER: DS 256 ; ruimte voor opslag +1FF - ; inhoud per segment -``` - -## O P D E D I S K - -Deze source is geschreven in WB-ASS2 en staat in ASCII op de -disk onder de naam "MEMCOUNT.ASC". Om de routine uit te -testen staat ook de file "MEMCOUNT.BIN" op deze Sunrise -Special #1. Deze file wordt geladen door "MEMCOUNT.BAS", dat -u in het softwaremenu kunt vinden. Dit programma laat zien -hoe u de routine vanuit BASIC kunt gebruiken. - - -## L E T O P - -U kunt deze routine normaal gesproken altijd gebruiken, -omdat hij het RAM niet blijvend aantast. Tijdens het lopen -van de routine wordt het RAM echter wel tijdelijke -aangetast. Het zou dus kunnen dat u een muziekje over de -interrupt laat lopen en dat dit programma in de driver zit -te POKEn en dan gaat het mis. De oplossing is simpel: -gewoon de interrupts uitzetten. Dus: -``` -DI -CALL MEMCNT -EI -``` -Misschien de volgende keer een uitbreiding waardoor de -routine meer dan ��n memorymapper aankan. Voor deze keer -laat ik het hierbij. - -Stefan Boer diff --git a/Sunrise Special/1/Het rel file formaat.md b/Sunrise Special/1/Het rel file formaat.md deleted file mode 100644 index 6b21be1..0000000 --- a/Sunrise Special/1/Het rel file formaat.md +++ /dev/null @@ -1,60 +0,0 @@ -# H E T . R E L F I L E F O R M A A T - -Een GEN80 REL bevat informatie gecodeerd in een bit-stream -dat als volgt ingedeeld is. - -Als de eerste bit een 0 is dan zullen de volgende 8 bits in -het adres van de location counter geladen worden. - -Als de eerste bit een 1 is dan volgen er 2 bits met de -volgende betekenis. - -00 Het is een special link item die onder beschreven -wordt. -01 Program relative item, de volgende 16 bits zullen in -het adres van de location counter geladen worden -nadat ze zijn opgetelt bij het basis adres van het -programma/code segment. -10 Data relative item, de volgende 16 bits zullen in -het adres van de loaction counter geladen worden -nadat ze zijn opgeteld bij het basis adres van het -data segment. - -Een special link item bestaat uit het volgende: - -1 Een 4 bits lange control field, onder beschreven. -2 Een adres field dat een 2 bits adress type field is, -gevolgd door een 16 bits adres. Het adres type field -bestaat uit het volgende. - -00 Het adres is absoluut. -01 Het adres is relatief aan het programma. -10 Het adres is relatief aam het data segment. - -3 Een optioneel naam veld dat bestaat uit een 3 bits -lengte teller gevolgd door de naam van de label in 8 -bits ASCII. - - -## H E T C O N T R O L F I E L D - -De volgende link items worden gevolgd door een naam veld: - -0000 Deze label is PUBLIC verklaard in deze module. -0010 De naam van dit programma. - -De volgend link item worden gevolgd door een adres field. - -0111 Geeft de waarde in het adres field aan de label in -het naam veld. - -De volgende link items worden alleen gevolgd door een adres -field: - -1010 Define data size. Het adres veld bevat het totaal -aantal byte in het data segment van deze module -1011 Set location counter, veranderd het adres van de -location counter -1110 End of module. Geeft het einde van deze module aan -De volgende heeft geen velden -1111 End of file. Geeft het einde van de file aan diff --git a/Sunrise Special/1/Hybride programmeren.md b/Sunrise Special/1/Hybride programmeren.md deleted file mode 100644 index 6a2c533..0000000 --- a/Sunrise Special/1/Hybride programmeren.md +++ /dev/null @@ -1,647 +0,0 @@ -# H Y B R I D E P R O G R A M M E R E N ( 1 ) - - -## I N L E I D I N G - -Dit is het eerste deel van een serie artikelen waarin ik wat -dieper in ga op het zogenaamde "Hybride programmeren", een -combinatie van BASIC en machinetaal. In de artikelen zal -vooral aandacht worden besteed aan de hulpmiddelen die de -MSX standaard biedt om de samenwerking beter te laten -verlopen, en waar men bij het hybride programmeren op moet -letten. - -Maar eerst zal ik uitleggen waar de naam hybride vandaan -komt. - - -## H Y B R I D E - -Het woord "hybride" komt zowel in de Nederlandse als in de -Engelse taal voor en betekent hetzelfde, namelijk het -resultaat van een kruising tussen twee verschillende -diersoorten. Bekende hybriden zijn muilezels, muildieren, -scheiten en gapen. Hybriden zijn altijd steriel, en bij het -fokken moeten afstotingsverschijnselen worden onderdrukt. -Maar genoeg biologie, terug naar MSX. - -Spreken we het woord op z'n Engels uit (haibraid), dan -bedoelen we er in de computerwereld iets anders mee: een -kruising tussen twee programmeertalen. Bij MSX is dat altijd -BASIC en machinetaal. Ik ga er in deze artikelen van uit dat -de lezer zowel BASIC als machinetaal in redelijke mate -beheerst. - - -## G R E N Z E N - -MSX BASIC heeft een werkgebied nodig voor het opslaan van -een BASIC programma en de daarbij behorende variabelen. Dit -werkgebied begint normaal gesproken op &H8000, maar dit kan -worden veranderd. Het adres waarop het BASIC programma -begint wordt opgeslagen op de volgende locatie: - -TXTTAB (&HF676, 2 bytes) Begin van "BASIC text area" - -Op (TXTTAB)-1 moet altijd een 0 staan. Normaal gesproken is -TXTTAB gevuld met de waarde &H8001, en bevat adres &H8000 -dus een 0. - -Na het veranderen van TXTTAB moet er een NEW worden gegeven, -zodat ook andere adressen (zoals het beginadres van de -variabelentabel) kunnen worden aangepast. Ditzelfde wordt -gedaan door een RUN"FILENAAM.BAS" of LOAD"FILENAAM.BAS" -instructie, er wordt dan door de BASIC interpreter eerst een -NEW uitgevoerd, en daarna wordt het BASIC programma geladen -en (bij RUN) ge�xecuteerd. U kunt dus na het veranderen van -TXTTAB ook een RUN"FILENAAM.BAS" of LOAD"FILENAAM.BAS" -commando geven. - -U kunt in BASIC het startadres van BASIC als volgt -veranderen: (veranderen naar &HC000) -``` -POKE&HF677,&HC0 -POKE&HF676,1 -POKE&HC000,0 -NEW -``` -Het kan ook vanuit een programma. Stel u wilt dat het -programma "EXAMPLE.BAS" op &HC000 staat. U kunt dat als -volgt programmeren: -``` -10 'EXAMPLE.BAS -20 IF PEEK(&HF677)<>&HC0 OR PEEK(&HF676)<>1 THEN -POKE&HF677,&HC0:POKE&HF676,1:POKE&HC000,0: -RUN"EXAMPLE.BAS" -30 ..... -``` -Vanaf regel 30 kunt u uw eigen programma invullen, save het -programma als "EXAMPLE.BAS". Wordt dit programma geladen -terwijl het adres al goed staat, dan wordt er direct verder -gegaan met regel 30. Anders wordt het adres goed gezet en -laadt het programma zichzelf nogmaals in, alleen nu op het -goede adres. - -Het gebied vanaf &H8000 tot (TXTTAB)-1 mag door machinetaal -worden gebruikt, hier kan BASIC nooit komen. - -Ook achter het BASIC programma is nog een gebied dat door -machinetaal gebruikt kan worden. Dit kan voor BASIC worden -beschermd met de CLEAR instructie. - - -## C L E A R - -Dit is een veelgebruikte (en meestal noodzakelijke) -instructie bij hybride programmeren. Eerst maar de syntax -van het CLEAR commando: - -CLEAR [][,] - -Voor de stringruimte moet een grootte in bytes voor het -datagebied voor strings worden ingevuld. Standaard is dit -200. Bij programma's die veel strings gebruiken is dat niet -genoeg, er volgt dan een "Out of string space" foutmelding. -Zo'n foutmelding kan worden voorkomen door de stringruimte -met het CLEAR commando te vergroten. Alleen een CLEAR -commando, dus zonder parameters, wist alle variabelen. - -Voor het adres moet het hoogste adres dat door BASIC mag -worden gebruikt worden ingevuld. Lees dit goed, het adres -zelf mag dus nog door BASIC worden gebruikt. Wilt u dus een -werkgeheugen voor machinetaal vanaf adres &HD000 reserveren, -dan moet het commando als volgt luiden: - -CLEAR 200,&HCFFF - -En niet CLEAR 200,&HD000, omdat dan de eerste byte van het -machinetaalgedeelte toch door BASIC kan worden veranderd. In -een hybride programma dat het gebied boven het BASIC -programma gebruikt moet ALTIJD een CLEAR commando worden -gezet! - -Met het CLEAR commando wordt de inhoud van HIMEM veranderd, -maar CLEAR doet nog veel meer. Zoals het wissen van alle -variabelen en het verplaatsen van een aantal werkgebieden. - -HIMEM (&HFC4A, 2 bytes) Bevat het hoogste adres dat door -BASIC mag worden gebruikt. - -De stack verhuist dan mee naar het gebied onder (HIMEM). -(Tussen haakjes betekent "de inhoud van".) Zoals u weet -groeit de stack aan de onderkant aan. De top van de stack -wordt ook in het systeem gebied opgeslagen: - -STKTOP (&HF674, 2 bytes) Bevat de top van de stack. - -Behalve de stack worden ook de File Control Blocks (niet die -van de BDOS, maar van Disk BASIC, 267 bytes per stuk, aantal -in te stellen met MAXFILES) verplaatst. - - -## D E B O V E N G R E N S - -De ondergrens van het machinetaalprogramma wordt dus door -het CLEAR commando bepaald. Maar wat is de bovengrens? - -Bij een MSX computer zonder diskdrive is dat erg eenvoudig. -Het systeemgebied van de MSX begint namelijk op adres -&HF380, dus het gebied tot &HF37F is vrij voor eigen -gebruik. - -Bij ��n of meer aangesloten diskdrives wordt de situatie -anders. De diskROM gebruikt namelijk een stuk geheugen onder -&HF380 als werkgeheugen, en de grootte van dat werkgebied -kan behoorlijk vari�ren. Dit is afhankelijk van het aantal -diskdrives en de grootte (enkelzijdig of dubbelzijdig) -daarvan. - -Meestal heeft een MSX2 computer 2 softwarematige drives, en -��n hardwarematige. Sommige luxe modellen hebben twee -hardwarematige drives (een hardwarematige drive is een echte -diskdrive, waar je een diskette in kunt steken, en een -softwarematige drive is een drive die door de diskROM wordt -ondersteund. Heeft een computer maar ��n hardwarematige -drive, dan zal de diskROM de softwarematige B: drive -simuleren met een "Insert diskette for drive B:" op de A: -drive). De tweede softwarematige drive kan worden -afgekoppeld door met de [CTRL] toets ingedrukt op te -starten. Hierdoor komt het werkgeheugen dat eerst voor de -softwarematige B: drive werd gebruikt vrij voor gebruik door -BASIC of machinetaal. - -Het maakt ook uit of de diskdrive enkelzijdig of -dubbelzijdig is. Er kunnen ook nog meer diskdrives actief -zijn, als er bijvoorbeeld een extra losse interface in een -cartridgeslot wordt gestoken. - -Tot slot speelt ook het actieve disk besturingssysteem een -rol. Bij Disk BASIC 1.0 (DOS1) is een veel groter werkgebied -nodig dan bij Disk BASIC 2.01 (DOS2). Kortom, u mag er nooit -vanuit gaan dat het werkgeheugen van de diskROM op elke -computer hetzelfde is. - -Waar mag u dan wel van uit gaan? Als u de computer opstart -bevat HIMEM altijd de juiste waarde. Het geheugen onder dat -adres wordt niet door de diskROM gebruikt, en kan dus veilig -voor machinetaal worden gebruikt. BASIC zorgt er zelf wel -voor dat het werkgeheugen van de diskROM niet wordt -overschreven. - -Lees direct na het opstarten dus HIMEM uit, en controleer of -uw machinetaal niet boven dat adres uit komt. Is dat toch -zo, geef dan een melding "Reset met [CTRL]" of iets -dergelijks, en stop de executie van het programma. Is er -niets aan de hand, dan kunt u rustig verder gaan met het -programma. Als zelfs het opstarten met [CTRL] niet helpt, -dan is kan het programma helemaal niet op die computer -worden gedraaid, in ieder geval niet in die configuratie. De -gebruiker kan dan bijvoorbeeld de C: en D: drive afkoppelen. - -Het is belangrijk om HIMEM uit te lezen voordat u een CLEAR -geeft, omdat CLEAR de waarde van HIMEM verandert. Het CLEAR -commando hoort trouwens vooraan het BASIC programma, omdat -het alle variabelen wist. - - -## V E I L I G E B O V E N G R E N S - -Bij bovenstaande methode moet er toch een bovengrens worden -gekozen. En het liefst een die op alle computers werkt, en -het liefst een waarbij niet met [CTRL] hoeft te worden -opgestart. Houd de bovengrens altijd zo laag mogelijk. -&HD7FF is een zeer veilige waarde, die met vrijwel geen -enkele configuratie problemen zal geven. - - -## S T A C K - -Houd wel rekening met de stack. In principe geeft die geen -problemen, maar als u eigenwijs toch geen CLEAR commando -gebruikt, dan staat de stack ergens een paar honderd bytes -onder de waarde van HIMEM bij het opstarten. - -Misschien is het even handig om de geheugenindeling onder -BASIC te geven: - -- BASIC programma -- Variabelen -- Arrays -- Vrij -- Stack -- Strings -- File Control Block -- Machinetaalprogramma -- Werkgebied Disk BASIC -- Werkgebied BIOS - - -## H I M E M O P S L A A N - -Als de besturing aan het eind van het programma weer -volledig aan BASIC wordt overgedragen, zorg dan dat HIMEM en -TXTTAB weer terug worden gezet. Zet TXTTAB daarbij op &H8001 -(vergeet niet de POKE &H8000,0) en zet HIMEM op de waarde -die er bij het opstarten in stond. Om dit te kunnen doen is -het nodig dat de waarde van HIMEM direct na het opstarten op -een veilige plaats wordt bewaard. - -We weten nu hoe we ervoor kunnen zorgen dat het BASIC -werkgebied, het machinetaal werkgebied, het BIOS/BASIC -werkgebied en het diskROM werkgebied elkaar niet storen, dus -we kunnen beginnen met het eigenlijke hybride programmeren. - -## U S R - -Bij hybride programmeren wordt het USR commando van BASIC -het meeste gebruikt. Met DEFUSR kunnen 10 machinetaal- -routines worden gedefinieerd. Dit gaat als volgt: - -DEFUSR= - -Waarbij voor een getal van 0 t/m 9 wordt ingevuld -(weglaten = 0) en voor het beginadres van de -machinetaalroutine. Voorbeeld: - -DEFUSR3=&HD000 - -De machinetaalroutine die op adres &HD000 begint kan nu -worden opgeroepen met USR3. De DEFUSR adressen worden in het -werkgebied opgeslagen in de tabel USRTAB, die begint op -adres &HF39A. Deze tabel bevat 10 adressen van 2 bytes per -stuk, en is dus 20 bytes lang. POKE &HF39A,0: POKE -&HF39B,&HC0 is dus hetzelfde als DEFUSR=&HC000. - -Het aanroepen van een machinetaalroutine gaat door het -opvragen van een waarde! Het USR commando is dus eigenlijk -een functie. Aan het USR commando kan ��n parameter worden -meegegeven. De syntax luidt als volgt: - -USR() - -Voor het moet weer een getal van 0-9 worden -ingevuld. De parameter kan niet worden weggelaten. Het USR -commando wordt als functie gebruikt. Een paar voorbeelden: -``` -U=USR(0) -PRINT USR3("HALLO") -A$=USR2(X$)+USR5(3) -PRINT USR6(3)*USR7("D") -P=3+USR(8.8354743) -X=LEN(USR9(5)) -``` -Als de waarde van USRx wordt opgevraagd, wordt naar het -adres dat met DEFUSRx is gedefinieerd gesprongen. De -parameter kan door het machinetaalprogramma worden -uitgelezen, en het machinetaalprogramma kan ook het -resultaat weer aan BASIC doorgeven. Dit is dus de "waarde -van USRx". Dit kan een getal zijn (INT, SNG of DBL), maar -ook een string. Hoe gaat dit doorgeven van parameters nu in -zijn werk? - -## D A T A U I T W I S S E L I N G - -Als een USR wordt aangeroepen springt de BASIC interpreter -niet meteen naar de machinetaalroutine, maar zal eerst een -aantal dingen doen. Een daarvan is het opslaan van de -parameter die tussen haakjes staat op een vaste plaats. - -Op VALTYP (&HF663) wordt het type variabele gezet. Hiervoor -gebruikt BASIC altijd dezelfde getallen, die overeenkomen -met de ruimte die de opslag van zo'n variabele in beslag -neemt (bij de stringvariabele is dat exclusief de string -zelf!). Een tabel: - -(VALTYP) Soort variabele: Voorbeelden: ------------------------------------------------------------- -2 integer (INT) A%, 32767 -3 string (STR) A$, "Sunrise" -4 enkele precisie (SNG) A!, 1.23456 -8 dubbele precisie (DBL) A#, 1.2345678901234 ------------------------------------------------------------- - -Deze waarde wordt bovendien in het A register geladen. Wilt -u bijvoorbeeld voordat u verdergaat met de rest van de -routine controleren of de parameter wel een integer is, dan -ziet dat er in ML zo uit: -``` - CP 2 ; parameter INT? - RET NZ ; nee, dan einde -``` -Het HL register bevat altijd de waarde &HF7F6, het -beginadres van DAC. Bij parameters van de typen INT, DBL en -SNG wordt de inhoud in DAC opgeslagen. Dit gaat als volgt: - -INT: DAC+2 bevat low byte - DAC+3 bevat high byte - -SNG: DAC+0 t/m DAC+3 bevatten getal in BCD formaat - -DBL: DAC+0 t/m DAC+7 bevatten getal in BCD formaat - -De behandeling van het BCD formaat valt buiten dit artikel. -Dit zal uitgebreid aan bod komen bij de behandeling van de -Math Pack (de rekenroutines van de BASIC interpreter). Dit -zal zeker op een komende Sunrise Special worden behandeld, -het is nu nog niet bekend op welke. - -Bij een string staat op adres &HF7F8 het adres waar de -zogenaamde "string descriptor" begint. Ditzelfde adres staat -ook in het DE register. De string descriptor ziet er als -volgt uit: - -+0 lengte van de string (0-255) -+1 low byte van beginadres van string -+2 high byte van beginadres van string - -Verderop in het artikel zullen een aantal voorbeeldlistings -volgen. Maar nu eerst het doorgeven van variabelen aan -BASIC. - -Als de machinetaalroutine geen variabele aan BASIC hoeft -terug te geven, dan kunt u de machinetaalroutine gewoon met -een RET be�ndigen. Anders moet voor de RET eerst DAC en -VALTYP met de juiste waarde worden gevuld. - -Zet de juiste waarde in VALTYP. Is het dezelfde soort -variabele als de parameter die werd doorgegeven, en heeft u -VALTYP in de routine niet veranderd, dan hoeft u dit -natuurlijk niet te doen. Door VALTYP te veranderen is -bijvoorbeeld zoiets mogelijk: - -A!=USR(B$) - -De waarden van de registers mogen allemaal worden veranderd. -A hoeft dus niet het type te bevatten en HL niet het -beginadres van DAC (en bij strings DE niet het beginadres -van de string descriptor), zoals bij de aanroep van een -routine door USR. BASIC kijkt daar namelijk helemaal niet -naar. Het vullen van HL en A (bij strings DE) met de juiste -waarden is alleen maar extra service van BASIC. - -Waar BASIC w�l naar kijkt is de inhoud van VALTYP en de -inhoud van DAC. Bij INT, DBL en SNG variabelen is het vullen -van DAC met de juiste waarde voldoende. Bij strings is er -echter een probleem. - - -## S T R I N G S - -Het doorgeven van een string aan een machinetaalroutine kan -erg handig zijn en geeft geen enkel probleem. Het doorgeven -van een string door een machinetaalroutine aan BASIC kan -echter wel grote problemen opleveren. - -De vraag daarbij is namelijk: waar moet die string in het -geheugen worden gezet? We gaan nu even uit van de situatie -A$=USR(B$). - -Als de resultaat-string even lang of korter is dan B$, en -als het niet erg is als de waarde van B$ verloren gaat, dan -is er geen probleem. Schrijf in de machinetaalroutine gewoon -het resultaat over de oude string heen, en klaar is Kees. -Indien nodig kan in de stringdescriptor de lengte worden -aangepast (alleen verkort!). - -Mag de string echter niet langer worden, of als B$ niet mag -worden overschreven, waar moet de resultaat-string (die door -BASIC aan A$ wordt doorgegeven) dan naartoe? - -Boven de CLEAR grens kan niet, omdat BASIC dan in de war -raakt. Strings mogen immers niet boven de CLEAR grens staan! -Ik heb deze manier zelf wel eens gebruikt, en bij mij werkte -het prima. Tot ik trots mijn programma ergens anders liet -zien, en de vreemdste teksten op het scherm werden getoverd. - -Het geheugen onder de CLEAR grens wordt door de BASIC -interpreter beheerd, je kan daar dus niet zomaar ergens een -string neer gaan zetten. De enige oplossing zou zijn om de -BASIC interpreter dit werk voor je te laten doen, maar -daarover heb ik onvoldoende documentatie. Gelukkig komt het -toch zelden voor dat je een machinetaalroutine wilt -schrijven waarbij het resultaat een string is. - - -## H O O F D L E T T E R S - -De eerste voorbeeld assemblerlisting zet van de string alle -kleine letters om in hoofdletters. Hier is de -assemblerlisting, regelmatig onderbroken voor uitleg. -``` -; C A P S . A S M -; Zet alle kleine letters in een string om in hoofdletters -; Door Stefan Boer, 2 juli 1992 -; (c) Stichting Sunrise 1992, Sunrise Special #1 - -FCERR: EQU &H475A ; BIOS error "Illegal - ; function call" - - ORG &HD000 - - CP 3 - JP NZ,FCERR ; error als geen string -``` -Register A bevat de soort variabele. Dit moet een string -zijn, met code 3. CP 3 vergelijkt A met de waarde 3. Is het -niet gelijk (NZ) dan volgt er een Illegal function call. -``` - LD A,(DE) - AND A - RET Z ; controle op lege string - LD B,A ; B=lengte - INC DE - LD A,(DE) - LD L,A - INC DE - LD A,(DE) - LD H,A ; HL=beginadres -``` -Hier wordt de stringdescriptor gelezen. De descriptor (= -"beschrijver") begint op het adres waar DE naar wijst. De -lengte van de string wordt in B gezet en het beginadres van -de string in HL. Als het een lege string is wordt er meteen -teruggesprongen naar BASIC. -``` -LOOP: LD A,(HL) - CP "a" - JR C,NEXT - CP "z"+1 - JR NC,NEXT - RES 5,A ; maak hoofdletter van - ; kleine letter - LD (HL),A -NEXT: INC HL - DJNZ LOOP ; herhaal voor hele string - - RET ; VALTYP en DAC hoeven niet - ; te worden veranderd -``` -Dit gedeelte zet de kleine letters om in hoofdletters. Eerst -wordt er gecontroleerd of het teken wel tussen a en z ligt. -Zo ja, dan wordt bit 5 gereset. Met een voorbeeld kunt u -zien hoe dat werkt. Een paar binaire ASCII codes: -``` -A &B01000001 -a &B01100001 -S &B01010011 -s &B01110011 - ^ - bit 5 -``` -Zoals u ziet bepaalt bit 5 of het een hoofd- of kleine -letter is (0=hoofd, 1=klein). - -De string wordt in dit voorbeeld gewoon overschreven. Stel u -heeft bovenstaande assemblerlisting geassembleerd, de -machinetaal staat dus op adres &HD000. Dan kunt u het -volgende BASIC programma uitvoeren: -``` -10 DEFUSR=&HD000 -20 A$="Sunrise" -30 B$=USR(A$) -``` -In dit geval bevatten zowel A$ als B$ na afloop "SUNRISE". -Mag de waarde van A$ niet verloren gaan, dan kunt u het -voorbeeld zo doen: -``` -10 DEFUSR=&HD000 -20 A$="Sunrise" -30 Q$=A$:B$=USR(Q$) -``` -Er gebeurt iets grappigs als u met een constante werkt: -``` -10 DEFUSR=&HD000 -20 U$=USR("Sunrise") -``` -Na het RUNnen van dit programma bevat de variabele U$ -uiteraard "SUNRISE". Typt u nu maar eens LIST in. Dit is wat -u dan te zien krijgt: -``` -10 DEFUSR=&HD000 -20 U$=USR("SUNRISE") -``` -Dus ook in het BASIC programma is de tekst in hoofdletters -omgezet. Dit komt omdat de BASIC interpreter de string -descriptor in dit geval gewoon naar de constante "Sunrise" -in het BASIC programma laat wijzen. - -U snapt nu wel dat het doorgeven van strings van machinetaal -aan BASIC nogal problematisch gaat. Andersom gaat het prima. - - -## T E K S T J E P R I N T E N - -Dit is een goed voorbeeld van een string doorgeven aan -machinetaal. Onderstaande assemblerlisting zet de string die -als parameter aan USR wordt doorgegeven op het scherm. -``` -; P R I N T S T R . A S M -; Print een string -; Door Stefan Boer, 2 juli 1992 -; (c) Stichting Sunrise 1992, Sunrise Special #1 - -FCERR: EQU &H475A ; BIOS error "Illegal - ; function call" - - ORG &HD000 - - CP 3 - JP NZ,FCERR ; error als geen string - - LD A,(DE) - AND A - RET Z ; lege string - LD B,A ; B=lengte - INC DE - LD A,(DE) - LD L,A - INC DE - LD A,(DE) - LD H,A ; HL=beginadres -``` -Dit gedeelte is bijna gelijk aan de vorige routine, het -haalt de stringdescriptor op. -``` -PRINT: LD A,(HL) ; haal teken - CALL &HA2 ; teken naar scherm - INC HL ; volgende teken - DJNZ PRINT ; herhaal B maal - - RET -``` -Dit gedeelte zet de string op het scherm, en gebruikt de -BIOS routine CHPUT (&HA2). De volgende routine bewijst dat -het doorgeven van getallen in beide richtingen geen enkel -probleem oplevert. - - -## R E K E N E N - -Onderstaande routine doet iets ontzettend moeilijks, hij -telt 1 op bij het getal dat als parameter aan USR wordt -meegegeven!!! Geweldig he?! -``` -; P L U S 1 . A S M -; Telt 1 op bij een getal -; Door Stefan Boer, 2 juli 1992 -; (c) Stichting Sunrise 1992, Sunrise Special #1 - -DAC: EQU &HF7F6 -ILLEGA: EQU &H475A - - ORG &HD000 - - CP 2 - JP NZ,ILLEGA ; Illegal function call als - ; geen integer - LD HL,(DAC+2) ; lees waarde - INC HL ; plus 1 - LD (DAC+2),HL ; geef waarde door aan BASIC - RET -``` -Deze routine behoeft geen uitleg meer, alle uitleg is al -eerder in dit artikel gegeven. Toch zit er hier wel een -addertje onder het gras. Typt u bijvoorbeeld: -``` -PRINT USR(3) -``` -Dan zet de computer netjes een 4 op het scherm. Typt u -echter: -``` -A=3 -PRINT USR(A) -``` -Dan volgt er een Illegal function call. Hoe kan dat? Dat -komt omdat alle variabelen (tenzij anders bepaald met een -DEF commando) automatisch van het DBL type zijn. Overal waar -A staat moet u dus A# lezen. En natuurlijk krijg je dan een -illegal function call, omdat VALTYP dan een 8 bevat in -plaats van een 2. Deze fout kan worden voorkomen door DEFINT -A te typen, of door achter elke A een % te plaatsen. -``` -DEFINT A -A=3 -PRINT USR(A) -``` -Dit werkt wel. Nog een laatste opmerking: alle registers -mogen worden veranderd door een routine die met USR wordt -aangeroepen (behalve natuurlijk SP, want dan kan er na -afloop niet meer worden teruggesprongen naar de BASIC -interpreter). - - -## T O T S L O T - -Dit lijkt me wel voldoende voor deze keer, de eerste manier -van samenwerking tussen BASIC en ML (USR) is nu volledig -besproken. De volgende keer komt het volgende BASIC commando -voor deze samenwerking aan bod: CMD. Ik heb al een leuke en -vooral handige voorbeeldroutine klaarliggen. - -Wie heeft er meer ervaring met het stringprobleem, en weet -wel een goede oplossing? Reacties graag naar de Sunrise -postbus, ter attentie van ondergetekende. Ik ben zelf al -bezig geweest met een oplossing, dus misschien kom ik daar -de volgende keer zelf mee op de proppen. - -Stefan Boer diff --git a/Sunrise Special/1/MSX Assemblers.md b/Sunrise Special/1/MSX Assemblers.md deleted file mode 100644 index 7da6904..0000000 --- a/Sunrise Special/1/MSX Assemblers.md +++ /dev/null @@ -1,274 +0,0 @@ -# A S S E M B L E R S O P M S X - - -Het schrijven van machinetaalprogramma's op MSX is nooit -echt moeilijk geweest en is daarom ook een prima computer om -het op te leren. Er is in het verleden al veel geklaagd over -het feit dat men wel een modernere processor had kunnen -kiezen om in de MSX te stoppen, maar daarbij werd dan vaak -over het hoofd gezien dat de Z80 een makkelijk te begrijpen -microprocessor is (waarschijnlijk omdat hij een volledig -achterhaalde architektuur heeft). - -Dit verhaal is er op gericht om u kennis te laten maken met -de twee meest gebruikte assemblers op MSX. Deze assemblers -zijn WBASS-2 en GEN80. - - -## G E N 8 0 - -Dit is een redelijk oude assembler die nog uit het CP/M -tijdperk stamt. Het is echter in technisch opzicht een prima -assembler omdat hij redelijk flexibel is en omdat hij met -hele grote listings om kan gaan. - -De hele assembler zit in 1 .COM file en maakt gebruik van de -DOS commando regel om invoer en uitvoer te regelen. -Bij de aanroep kunnen verschillende dingen gespecifiseerd -worden zoals de maximale breedte van een label en dingen met -betrekking tot de uitvoer. - -Voordelen van GEN 80: -- Het is mogelijk om met GEN 80 gebruik te maken van include -files en van macro files. Vooral deze laatste optie is -makkelijk omdat je zo je eigen persoonlijke BIOS bij kunt -houden met routines die je vaak nodig hebt. -- De maximale filelengte van een te assembleren files hangt -feitelijk alleen van de hoeveelheid RAM van je computer af -en van het feit dat er 'maar' 720 kB op 1 disk past. - -Nadelen: -- Omdat de assembler steeds geladen moet worden is het -feitelijk ondoenlijk alleen van disk te werken omdat je -dan gewoon niets opschiet. Het gebruik van een RAM-disk is -eigenlijk onontbeerlijk omdat je anders het grootste deel -van de tijd staat te wachten. -- Omdat GEN 80 onder DOS loopt is het niet echt handig als -je iets wilt testen. Meestal moet je dan eerst naar BASIC -voordat je de creatie kunt testen. Je berijpt dat debuggen -zo een vervelende bezigheid wordt omdat je konstant tussen -DOS en BASIC zit te klooien. -- Het eigen gebruik van de memory mapper is ook niet aan te -bevelen als je op hetzelfde moment alles in een RAM-disk -hebt staan. De kans is dan groot dat je dingen in de -RAM-disk gaat overschrijven waardoor je alles weer opnieuw -moet installeren. - -GEN 80 is een prachtige assembler maar is helaas niet -speciaal voor MSX geschreven. Vooral bij het gebruik van de -memory mapper stoot je hier dus op problemen. Voor het -schrijven van demo's of andere soorten programma's die in -een grafische mode werken is het gebruik van GEN 80 af te -raden om de doodsimpele reden dat hij daar niet voor -geschreven is. - - -## W B A S S - 2 - -Dit is bij mijn weten de enige assembler die speciaal voor -MSX geschreven is. Ik moet hierbij meteen opmerken dat -WBASS-2 niet een assembler is, maar dat het een assembler -bevat. Verder behoren een monitor, een editor en een -disassembler tot de standaard uitrusting. Het gekke is dat -de voordelen en nadelen van GEN 80 precies omgekeerd van -toepassing zijn voor WBASS-2. Zo is het bij WBASS-2 oppassen -dat je niet over je source code heen assembleert, maar daar -staat tegen over dat het gebruik van de memorymapper een -fluitje van een cent is. - -Voordelen van WBASS-2: -- Het is een ge�ntegreerd pakket van ontwikkelsoftware dat -goed met elkaar samenwerkt en waarmee weinig tijd verloren -gaat aan het omschakelen tussen editten en bv. het testen -van een programma. -- Het is mogelijk om tegelijk een assembly programma en een -BASIC programma te gebruiken en te bewerken. -- De assembler is snel (op een turbo R zelfs hemels). -- De assembler is heel flexibel. Zo is het mogelijk om met -verschillende notaties voor getalrepresentatie te werken. -(Zie verder). -- Het pakket biedt een volledige ondersteuning van het -memory-map systeem van de MSX. -- De editor is speciaal geschreven voor de invoer van -assembly (alhoewel er dan altijd nog mensen zijn die -klagen over deze lovenswaardige eigenschap). -- Het pakket biedt een goede ondersteuning van de MSX -file-formaten. Zowel .BIN als .DAT files zijn probleemloos -te laden. -- De editor kan ASCII files genereren, maar het opslaan van -files kan beter in het WBASS-2 formaat gebeuren omdat deze -vorm korter en sneller is. -- Het is met een simpele aanpassing van het laadprogramma -mogelijk om de plaats van het WBASS-2 programma in het RAM -zelf te bepalen (Zet hem dus altijd in de hoogste vrije -RAM page die je hebt). - -Nadelen: - -- De lengte van de te bewerken file is beperkt tot ong. 23kB -- Je moet oppassen dat je niet over je eigen source code -heen schrijft. (Zie voor meer details bij Tips.) -- De Z80 mnemonics liggen redelijk goed vast, behalve die -van de instruktie EX AF,AF' Volgens offici�le Zilog -informatie is deze notatie de enige goeie, maar een aantal -andere Z80 fabrikanten vond dat zeker niet belangerijk en -hebben er EX AF,AF van gemaakt. Om verwarring te voorkomen -kunnen de meeste assemblers beide notaties wel aan, maar -WBASS-2 kan dit niet en zal bij gebruik van de eerste -variant een foutmelding geven. -- WBASS-2 heeft nog een paar kleine bugs die op het eerste -gezicht niet opvallen (zie Tips). -- WBASS-2 kent geen macro's en het include file mechanisme -is niet echt denderend. - -WBASS-2 bevat enkele bugs ! Zo is het gelijktijdig werken -met zowel enkel- als dubbelzijdige disks af te raden omdat -het programma hierdoor in de war kan raken met alle gevolgen -vandien. Dit is bij mijn weten de grootste bug van WBASS-2. -Er zijn geloof ik nog enkele, maar die zijn mij nog niet -opgevallen. - -De nadelen van WBASS-2 zijn met enige oefening en handigheid -op te heffen. Het is gewoon een kwestie van hoe je met het -programma om gaat. Voor MSX is WBASS-2 zonder enige twijfel -het beste pakket omdat het speciaal voor MSX geschreven is. -Hierbij zijn de twee belangerijkste kriteria de snelheid -waarmee tussen testen en assembleren geschakeld kan worden -en de sublieme manier van geheugen management dat het pakket -de gebruiker biedt. - - - Tips voor het gebruik van WBASS-2 - -Tips voor het instellen van het programma: -- In het laadprogramma wordt op een gegeven moment een -OUT &HFD instruktie gegeven vlak voordat de WBASS-2 file -geladen wordt. Deze OUT bepaald op welke RAM page het -programma geladen wordt. Indien je bv. 256 kB hebt zou je -dus het best OUT &HFD,15 kunnen geven omdat het programma -dan niet in de weg zit tijdens het ontwikkelen van je -software. -- De edit data van je eigen programma komt altijd op mapper -page 1 te staan (net als een BASIC programma) en om nu te -voorkomen dat je per ongelijk een programma over je eigen -edit data assembleert kan je het beste een andere page -selekteren (met het PAGE commando) zodat de assembler de -code niet over je source data heen kan schrijven. -Dit werkt echter alleen voor page 2 (&H8000 / &HC000) -omdat je page 3 eigenlijk moet laten staan. Je edit data -kan nl. makkelijk over adres &HC000 heen staan, maar daar -kan je code ook staan. Pas dus altijd op met wat je doet. -(Persoonlijk vind ik dit het allergrootste nadeel van -WBASS-2.) Het is gelukkig mogelijk om op disk te -assembleren inplaats van in RAM zodat je dit probleem op -kunt heffen. -- Het is in het laadprogramma ook mogelijk om het eerste -adres te kiezen voor editdata. Dit gebeurt met de -instruktie: BE=&H9200 Indien je dit adres op &H8000 zet -moet je wel oppassen dat je absoluut niet meer een BASIC -programma gaat invoeren omdat je dan meteen over je source -code heen schrijft. Je kunt deze waarde het beste op -&H8100 zetten zodat je naast je edit data ook nog een -klein BASIC programma in het RAM kunt hebben. -- De include optie van WBASS-2 is zoals vermeld niet echt -denderend. Het houdt feitelijk in dat je in een listing -kunt vermelden dat hij nog een file moet laden die ook -geassembleerd moet worden. Dit kan bij WBASS-2 alleen als -je de include opdracht onderaan de file neer zet omdat de -oude file uit de editbuffer gewist zal worden. Het is -daarom ook niet handig om deze optie te gebruiken omdat -het alleen maar ellende veroorzaakt. - -Voor verdere tips moet ik naar de uitstekende handleiding -verwijzen. - - -## G E T A L R E P R E S E N T A T I E - -Voor Z80 mnemonics bestaan 4 verschillende manieren van -getalsrepresentatie en wel: -- de binaire ( 2 tallig stelsel) -- de oktale ( 8 tallig stelsel) -- de decimale (10 tallig stelsel) -- de hexadecimale (16 tallig stelsel) - -Het is met een zgn. 'prefix' of 'postfix' mogelijk om aan de -compiler te vertellen welk talstelsel bedoeld wordt. In -BASIC zijn dit: -- &Bxxxxxxxx voor een binair getal -- &Oxxx voor een oktaal getal -- xx voor een decimaal getal -- &Hxx voor een hexadecimaal getal - -De meeste Z80 assemblers kunnen deze getalsrepresentatie ook -gebruiken. Er is echter een oudere notatievorm (die ik -persoonlijk wat eleganter vind) en die is als volgt: - -- xxxxxxxxB voor een binair getal -- xxxO voor een oktaal getal -- xx voor een decimaal getal -- xxH voor een hexadecimaal getal - -Hierbij moet opgemerkt worden dat bv. &H7FFF in de tweede -notatie als 07FFFH geschreven moet worden. Die extra 0 is -eigenlijk flauwekul omdat zo'n groot getal niet in een 16 -bits register past. (Nvdr. Die 0 is bij de meeste assemblers -alleen verplicht als het getal met een letter begint (dus -bijvoorbeeld 0F000H). Zo kan de assembler zien dat het om -een getal gaat en niet om een label.) - -WBASS-2 heeft als standaardinstelling de eerste notatievorm -maar kan ook de tweede gebruiken (met het SET commando in te -stellen). Dit is een hele handige optie als je bv. GEN80 -files om wilt zetten naar WBASS-2 files en dat gaat als -volgt. - -Geef op de WBASS-2 commandoregel de commando's: -SET/H a,"H" -SET/B a,"B" - -De getallen zullen nu bekeken worden volgens de tweede -notatievorm. Laad nu de om te zetten file die in ASCII -formaat moet staan. - -Doe nu: -SET/H v,"&H" -SET/B v,"&B" - -Als je nu weer EDIT in typt zullen alle getallen omgezet -zijn naar de eerste notatievorm. Nu hoef je alleen nog maar -het ' teken achter alle EX AF,AF' instrukties weg te halen -en de hele file is omgezet. Andersom werkt dit natuurlijk -ook. - - -Uitleg van begrippen die in dit artikel genoemd zijn - -Voor het geval je niet weet wat macro's zijn komt nu even -een korte uitleg. Macro's zijn vormen van labels die je -gewoon in je assembly code kunt zetten waarna de computer -tijdens het assembleren inplaats van dat label een aantal -instrukties neer gaat zetten. Meestal gebeurt dit in de vorm -van een subroutine. Op deze manier voorkom je dat je voor -elk programma de code van eigen BIOS routines hoeft te -kopi�ren, maar inplaats daarvan vermeld je aleen de file -waar je eigen BIOS calls in staan en hoef je alleen nog maar -de macro in je programma neer te zetten inplaats van de hele -routine. - - -## C O N C L U S I E - -Ik heb gemerkt dat mensen die met GEN 80 werken liever niet -omschakelen naar WBASS-2 en andersom. Ik heb in ieder geval -geprobeerd om een objektief oordeel over beide programma's -te geven. Aan GEN 80 is weinig meer te veranderen, maar -WBASS-2 zou nog uitgebreid kunnen worden. Indien de totale -ruimte voor edit data met 100 kB zou groeien en de gebruiker -precies zou kunnen bepalen waar deze data staat, dan zou -dat een zeer waardevolle aanvulling van het pakket zijn. -Vooral bij de wat grotere programma's wordt het lastig om -toch nog in het RAM te assembleren, maar voor de rest is -WBASS-2 de beste keus voor je MSX assembly creativiteit. - -Alex van der Wal diff --git a/Sunrise Special/1/Memman 2.3 intro.md b/Sunrise Special/1/Memman 2.3 intro.md deleted file mode 100644 index 3d2ef7d..0000000 --- a/Sunrise Special/1/Memman 2.3 intro.md +++ /dev/null @@ -1,391 +0,0 @@ -# M E M M A N 2 . 3 I N T R O D U C T I E - - -File : MM23INTRO.TXT c MST -Datum: 18 september 1991 -Door : Ries Vriend/Ramon van der Winkel/Robbert Wethmar - - - MST's MemMan 2, de MSX Memory Manager - -Begin 1990 riep MSX Computer Magazine voor het eerst de -beste MSX programmeurs van Nederland bij elkaar met de -bedoeling de MSX wereld nieuw leven in te blazen. De -programmeursgroep maakte kennis en er werden ideeen -uitgewisseld. Er bleek behoefte aan een Memory Manager, een -programma dat het geheugen van de MSX beheert. - -Met de Memory Manager worden twee doelen nagestreefd: - -1) Het zoeken en gebruiken van geheugen wordt eenvoudiger. -Het zoeken wordt door MemMan gedaan terwijl het gebruik -van geheugen zoveel mogelijk wordt losgekoppeld van de -configuratie: 'oude' uitbreidingen, een, twee of meer -mappers, MemMan heeft er geen moeite mee. -2) Het wordt mogelijk meerdere programma's tegelijkertijd in -het geheugen te laden zonder dat ze elkaar in de weg -zitten. Hierbij wordt gedacht aan RAMdisk's, -printerbuffers en op de achtergrond werkende programma's. - -Met versie 1 van MemMan - ge�ntroduceerd op 9 september 1990 -- is de eerste doelstelling bereikt. Nu is de tweede -doelstelling ook bereikt. - -MemMan versie 2 kan meerdere programma's 'ergens' in het -geheugen laden laten werken, zonder dat ze van elkaar last -hebben. Op andere computer merken was deze techniek al -langer bekend. Dergelijke programma's worden daar TSR's -genoemd, vandaar ook hier: Terminate and Stay Resident -programma's. - -Hopelijk zullen nog meer programma's van MemMan gebruik gaan -maken en bestaande programma's voor MemMan worden aangepast. -Een direct voordeel is dat het programma dan ook direct met -bijvoorbeeld 64 kB modules en zelfs met meerdere memory -mappers kan werken, iets dat de meeste bestaande programma's -niet of niet goed doen. - -MemMan versie 2 zal net als de eerste versie als Public -Domain de wereld in gestuurd worden. Dat wil zeggen dat -iedereen vrij van MemMan gebruik mag maken. Het is zelfs -toegestaan MemMan als onderdeel van een commercieel pakket -te verkopen. Alleen zo kan het programma uitgroeien tot een -aanvulling op de MSX standaard. Er zullen twee pakketten -uitgebracht worden. De eerst is voor de gebruiker van -MemMan. Dit pakket zal MemMan en een aantal tools voor de -TSR's bevatten. Het tweede pakket bevat ontwikkel tools en -technische documentatie over het programmeren van TSR's. Dit -laatste pakket is geen Public Domain. - - -Aan MemMan werkten en dachten mee: - -Ramon van der Winkel -Ries Vriend -Robbert Wethmar -Paul te Bokkel -Markus The -en een aantal anderen die met hun opbouwende kritiek MemMan -hielpen worden tot wat het is. - - - H E T C O N F I G U R E R E N - -MemMan is er in twee versies: een .BIN en een .COM file. Het -zal duidelijk zijn dat de .BIN versie vanuit BASIC met een -BLOAD"MEMMAN.BIN",R instructie geladen kan worden, terwijl -de .COM vanuit MSXDOS gestart kan worden door simpelweg -MEMMAN in te tikken. Beide versies keren na het laden - via -een zogenaamde warm boot - automatisch terug naar BASIC. Als -de .COM versie vanuit MSXDOS opgestart wordt, dan kan een -commandline mee gegeven worden. Dit zijn commando's welke -uitgevoerd zullen worden alsof ze ingetikt zijn. Een Return -kan met het @ teken worden opgegeven. Er kunnen meerdere @ -tekens in de commandline worden opgegeven, zodat meerdere -commando's na elkaar uitgevoerd kunnen worden. - -Bijvoorbeeld: - -A>MEMMAN _SYSTEM@TL CAPS@ - -Na het opstarten van MEMMAN zal naar MSXDOS teruggekeerd -worden en de TSR "CAPS" ingeladen worden. - -Met behulp van CFGMMAN is het mogelijk een aantal -instellingen van MemMan en een default commandline op te -geven. CFGMMAN kan zowel de .COM als de .BIN versie -configureren. Met betrekking tot de TSR's kunnen de volgende -instellingen veranderd worden: - -- Default command line -Hier kan de standaard commando-regel ingevoerd worden. Deze -commando-regel wordt uitgevoerd nadat MemMan ge�nstalleerd -is. Na het laden van de .BIN versie van MemMan wordt altijd -de standaard commando-regel uitgevoerd. De standaard -commando-regel wordt niet uitgevoerd indien MemMan vanuit -DOS opgestart wordt met een commando regel als argument. Na -foutmeldingen van MemMan wordt geen commando regel -uitgevoerd. - -- Heap grootte -Sommige TSR programma's hebben extra geheugen nodig in -geheugen pagina 3, waar ze normaal gesproken geen toegang -toe hebben. De heap is een stuk geheugen in pagina 3 dat wel -voor TSR's toegankelijk is. Wanneer een TSR meldt dat er te -weinig heap geheugen beschikbaar is dient deze waarde -verhoogd te worden. Meestal zal het toevoegen van 100 extra -bytes heap-geheugen de problemen uit de wereld helpen. -Wanneer een TSR meer heap-ruimte nodig heeft dient de -handleiding dat te vermelden. - -Elke verandering van de heap-grootte heeft slechts effect na -het opnieuw laden van MemMan. - -- Maximum aantal TSR's dat tegelijk aanwezig kan zijn -Het aantal TSR's dat onder MemMan 2 geladen kan worden is -beperkt. Wanneer de TSR Loader (TL) de melding 'TSR Table -Full' geeft dient deze waarde verhoogd te worden. - -- Maximum aantal hooks dat tegelijk afgebogen kan zijn -Het aantal hooks dat door alle in het geheugen aanwezige -TSR's kan worden afgebogen is beperkt. Wanneer de TSR Loader -de melding 'Hook Table Full' geeft dient deze waarde -verhoogd te worden. - -- Recursiediepte -Wanneer TSR's elkaar of zichzelf te vaak aanroepen zal het -systeem op een gegeven moment vastlopen. Door de maximale -recursiediepte te verhogen kunnen deze problemen voorkomen -worden. TSR's die zichzelf aanroepen dienen dat - met de -benodigde recursiediepte - te vermelden in de handleiding. - - - H E T I N S T A L L E R E N - -Om MemMem vanuit MSX-DOS te laden is het intikken van -`MEMMAN' achter de `>'-prompt voldoende. Vanuit BASIC dient -het commando BLOAD "MEMMAN.BIN",R ingevoerd te worden. Na de -installatie van MemMan wordt in beide gevallen BASIC -gestart, waarna de standaard commando regel uitgevoerd -wordt, zoals opgegeven in het configuratie programma -CFGMMAN. De standaard commando-regel wordt niet uitgevoerd -indien MemMan vanuit DOS gestart wordt met een vervangende -commando-regel als argument. - -Versie 2 van MemMan neemt behalve een stuk BASIC-geheugen -ook een 16 kB segment in beslag. Hierdoor blijft er onder -BASIC en MSXDOS zoveel mogelijk geheugen beschikbaar. De -ruimte die in het 16 kB segment over is wordt indien -mogelijk gebruikt om TSR's in onder te brengen. De -hoeveelheid BASIC-geheugen die MemMan gebruikt kan be�nvloed -worden door middel van het configuratieprogramma CFGMMAN. - -Wanneer MemMan onder DOS2 ge�nstalleerd wordt blijven alle -segmenten - behalve die ene die MemMan zelf nodig heeft - -ook voor DOS2 beschikbaar. Het is dus zonder meer mogelijk -eerst MemMan te installeren en daarna een DOS2 RAMdisk. - -Alvorens zichzelf in het RAM te nestelen controleert MemMan -natuurlijk of er al een versie van MemMan aanwezig is. In -dat laatste geval verschijnen de info-regels, aangevuld met -de mededeling dat MemMan reeds ge�nstalleerd is. Verder -gebeurt er niets. De commandoregel wordt gewoon uitgevoerd. - - - Terminate and Stay Resident programma's - -Gewoonlijk zal een programma na uitvoering niet in het -geheugen achterblijven. Programma's die dat wel doen worden -aangeduid met de afkorting TSR: Terminate and Stay Resident. -Voorbeelden van dergelijke programma's zijn: printerbuffers -en RAMdisks. Maar ook andere toepassingen, zoals een -rekenmachine of een kalender die met een enkele toetsdruk -opgeroepen kan worden zijn denkbaar. - -In het verleden zijn TSR's voor de MSX een tamelijk zeldzaam -verschijnsel geweest. Het probleem was namelijk dat het -geheugen dat de TSR gebruikt ook door andere programma's -gebruikt kan worden. Er zijn in een standaard MSX machine -geen mogelijkheden om een stuk geheugen voor een TSR te -reserveren. Dit probleem wordt door MemMan uit de wereld -geholpen. MemMan beheert het geheugen en zorgt er voor dat -er geen geheugenconflicten optreden. - -Dankzij MemMan is het mogelijk meerdere TSR's tegelijk in -het geheugen te hebben, waarbij elke TSR maximaal 16 kB -groot kan zijn. Op de standaard MSX is het laden van meer -dan ��n TSR al lastig en alleen mogelijk als de TSR niet al -te groot is. Met de invoering van MemMan 2 krijgt de MSX -betere TSR mogelijkheden dan de alom gewaardeerde PC. -Bovendien doen ze niet onder voor de `Desktop Accesoires' -zoals die op de Macintosh en de Atari ST gebruikt worden. - -Bij MemMan worden twee eenvoudige voorbeeld TSR's geleverd. -Ze doen weinig zinvols, maar demonstreren wel degelijk de -kracht vn Terminate and Stay Resident programma's. De -voorbeelden zijn CAPS.TSR en BEEP.TSR. De eerste laat het -Caps lampje knipperen, de tweede maakt dat het Basic -commando CMD BEEP een pieptoontje genereerd. In de toekomst -zullen er echter meer en meer TSR's verschijnen, met -mogelijkheden waar de MSX gebruiker tot voor kort alleen -maar van kon dromen. - - T S R S L A D E N - -TSR programma's zijn te herkennen aan de extensie van de -bestandsnaam: ze eindigen op .TSR. Deze files bevatten naast -de eigenlijke programmacode ook alle informatie die nodig is -om de TSR goed in het geheugen te installeren. - -Om bijvoorbeeld de demonstratie TSR 'CAPS' - die overigens -niets anders doet dan het Caps lampje laten knipperen - te -laden moet onder MSX-DOS ingetikt worden: - -TL CAPS - -Er mogen meerdere TSR-bestandsspecificaties achter elkaar -worden opgegeven. Indien MSX-DOS2 gebruikt wordt, mag ook de -subdirectory worden opgegeven, waaruit de TSR geladen moet -worden. Bijvoorbeeld, door middel van het volgende commando -worden zowel de TSR `CAPS' ingeladen, als ook alle TSR's -waarvan de bestandsnaam begint met `DEMO'. - -TL CAPS DEMO* - -`TL' betekent `TSR-Load', het is het programma dat de TSR -laadt en in het geheugen plaatst. Ook onder BASIC is een -versie van TSR-Load beschikbaar, zie hiervoor het hoofdstuk -`MemMan BASIC statements'. - -Zodra TL de TSR in het geheugen geinstalleerd heeft zal het -programma actief worden. In bovenstaand voorbeeld wil dat -zeggen dat het CAPS lampje zal gaan knipperen en bij iedere -toetsaanslag het cassetterelais aan of uit geschakeld wordt. - -TL is een slim programma. Zolang er in het MemMan segment -nog ruimte is voor TSR's zullen ze daar geplaatst worden. -Alleen als dat ook echt nodig is wordt een nieuw segment -gebruikt, dat voor overige toepassingen dan onbereikbaar -gemaakt wordt. Dat gebeurt bijvoorbeeld als er een -uitzonderlijk groot TSR programma wordt geladen. Wanneer er -vervolgens weer een kleinere wordt geladen zal TL eerst alle -bestaande TSR segmenten aflopen om te zien of er ergens nog -ruimte is. De volgorde waarin de TSR's geladen worden zal -dan ook geen invloed hebben op het geheugengebruik. - - - T S R S B E K I J K E N - -Het is ten aller tijde mogelijk te kijken welke TSR's er op -dit moment in het geheugen actief zijn. Daartoe bevat het -MemMan pakket de utility TV, TSR-View. Het gebruik is de -eenvoud zelf: gewoon achter de DOS prompt intikken: - -TV - -Er zal een overzicht verschijnen van de op dit moment -actieve TSR's, compleet met hun volledige naam. Deze naam -moet voor iedere TSR uniek zijn, en zal dan ook vrijwel -altijd de initialen van de programmeur bevatten. Deze naam -is dus een andere dan de bestandsnaam! - -Het is deze volledige naam - het TSR ID - die nodig is als -een TSR uit het geheugen verwijderd moet worden. Ook -programma's die direct met TSR's samenwerken kunnen deze -naam gebruiken om te zien of een TSR in het geheugen -aanwezig is. - - - - T S R S V E R W I J D E R E N - -Zoals gezegd is het ook mogelijk TSR programma's weer uit -het geheugen te verwijderen. Het benodigde programma heet -TK, TSR-Kill. TK zorgt er voor dat een TSR netjes verwijderd -wordt. Alle andere TSR's blijven vlekkeloos doorwerken, als -de TSR als enige in een segment stond wordt dat segment weer -vrijgegeven voor gebruik door overige toepassingen. - -Om bijvoorbeeld het het Caps lampje weer normaal te laten -werken en het knipperen uit te schakelen is het verwijderen -van de betrokken TSR voldoende. Daartoe tikt u: - -TK "MJVcapsblink" - -Hierbij dient de volledige naam van de TSR tussen -aanhalingstekens opgegeven te worden. Er kunnen meerdere -TSR's in ��n keer worden verwijderd, door de namen achter -elkaar in te voeren. Bijvoorbeeld: - -TK "TSR naam 1" "TSR naam 2" "TSR naam 3" - -TSR-Kill kan behalve geheugen weer vrijmaken voor gebruik, -ook gebruikt worden om vastgelopen TSR's uit het geheugen te -verwijderen. Een TSR die om welke reden dan ook niet meer -vlekkeloos functioneert zal met behulp van TK meestal nog -wel verwijderd kunnen worden. Vervolgens kan de TSR met TL -weer geladen worden, op dezelfde manier als het opnieuw -starten van gewone programma's nog wel eens wil helpen geldt -dat ook voor TSR's. - - -M E M M A N B A S I C - S T A T E M E N T S - -Vanaf versie 2.3 bevat MemMan enkele statements en functies -die vanuit MSX-BASIC toegepast kunnen worden. Hiertoe is -MemMan van een systeem TSR voorzien, met de ID-naam "MST -TsrUtils". Deze TSR heeft volgnummer 0 en kan niet door -TSR-Kill verwijderd worden. Hieronder volgt een beschrijving -van de beschikbare BASIC-instructies. De betekenis van de -gebruikte symbolen is als volgt: - -[] Wat tussen vierkante haken staat mag worden weggelaten. -<> Omschrijvingen van parameters staan tussen gehoekte -haken. -()", Ronde haken moeten worden ingetikt, evenals leestekens -en comma's. - - -Commando: TSR-Load -Syntax: CMD TL("",[T],[],[]) -Soort: Statement -Voorbeeld:CMD TL("PB") -CMD TL("ALARM",T,,A) -Functie: Laadt een TSR-bestand in het geheugen. - = Naam van het TSR-bestand. Onder - MSX-DOS2 mag een subdirectory worden - opgegeven. -T = Toon de intro-tekst van de TSR. - = Naam van een string-variabele waarin - de TSR ID-naam zal worden opgeslagen. - = Variabele waarin een foutcode wordt - opgeslagen. Indien deze variabele - wordt weggelaten, zal in geval van - laadfouten een standaard BASIC- - foutmelding worden gegeven. De - foutcodes zijn als volgt: - - 0 = TSR met succes ingeladen - 1 = Installatie door de TSR afgebroken - 2 = Structuurfout in TSR bestand - 3 = TSR-tabel vol - 4 = Hook-tabel vol - 5 = Geen vrij MemMan segment - 6 = Te weinig vrij BASIC werkgeheugen - - -Commando: TSR-Kill -Syntax: CMD TK("") -Soort: Statement -Voorbeeld:CMD TK("MJV printbuf") -Functie: Verwijdert een TSR uit het geheugen. - = Identificatienaam van de te - verwijderen TSR. Deze naam kan - worden opgevraagd door middel van - TSR-View of Find-TSR. - - -Commando: TSR-View -Syntax: CMD TV -Soort: Statement -Functie: Toont een overzicht van de ID-namen van alle -actieve TSR's. - - -Commando: Find-TSR name -Syntax: ATTR$ FT("") -Soort: Functie -Voorbeeld:IF ATTR$ FT("CAPS") THEN CMD TK("CAPS") -Functie: Levert de waarde -1 indien de opgegeven TSR is -ge�nstalleerd, levert anders de waarde 0. - = Identificatienaam van de TSR. - - -Commando: Find-TSR number -Syntax: ATTR$ FT() -Soort: Functie -Voorbeeld:N$ = ATTR$ FT(0) -Functie: Levert de ID-naam van de TSR met het opgegeven -volgnummer. Indien het volgnummer groter is dan -het aantal actieve TSR's, dan wordt een lege -string met lengte 0 teruggeven. \ No newline at end of file diff --git a/Sunrise Special/1/Memman 2.3 specificaties.md b/Sunrise Special/1/Memman 2.3 specificaties.md deleted file mode 100644 index 9864dc1..0000000 --- a/Sunrise Special/1/Memman 2.3 specificaties.md +++ /dev/null @@ -1,641 +0,0 @@ -# M E M M A N 2 . 3 S P E C I F I C A T I E S - - -File : MM23SPEC.TXT -Datum: 19 september 1991 -Door : Ries Vriend / Ramon van der Winkel - c MST - -Deze tekst bevat de informatie die nodig is voor het -schrijven van MemMan 2.3 toepassingsprogramma's. Voor -specifieke specificaties omtrend het programmeren van TSR's -wordt echter verwezen naar de technische documentie die te -vinden is op de `TSR-Development disk'. Hierop staan de -volledige TSR specificaties en enkele TSR ontwikkel tools. -Deze disk kan besteld worden bij het MST, zie voor meer -informatie hierover de LezersService van MSX Computer -Magazine. - - -Wijzigingen in MemMan 2.3 ten opzichte van versie 2.2: - -- De functie XTsrCall (61) is toegevoegd. Deze functie werkt -identiek aan de functie TsrCall (63), het Tsr-ID wordt -echter verwacht in register IX in plaats van BC. Hierdoor -komt register BC vrij om als invoerparameter gebruikt te -worden. - -- Door middel van de functie Info (50) kan het adres worden -opgevraagd waarop XTsrCall rechtstreeks kan worden -aangeroepen. - -- De funtie status (31) is verbeterd. De totale hoeveelheid -bruikbaar werkgeheugen in de computer wordt nu correct -gemeld, ook onder MSX-DOS2. - -- De Alloc (10) functie herkent nu ook geheugen dat -beschikbaar komt wanneer de DOS2 RAMdisk wordt verwijderd of -verkleind! Het maakt daarbij niet meer uit of de RAMdisk -wordt aangemaakt voor- of nadat MemMan werd ge�nstalleerd. - -- De interne stack van MemMan die gebruikt worden om -functieaanroepen te verwerken is vergroot tot 240 bytes, in -plaats van 160. In de praktijk bleek dat de functiestack van -MemMan 2.2 te krap was om geneste "tsrCalls" te verwerken. - - - G E B R U I K T E T E R M I N O L O G I E - -Segment - Geheugenblok van 16kB. Segmenten komen voor in -Pagina specifieke segmenten (PSEG) en Flexibele segmenten -(FSEG). De Flexibele segmenten kunnen op de pagina's 0,1 en -2 worden aangeschakeld. De Pagina specifieke segmenten -alleen op hun eigen pagina. Er zijn drie soorten pagina -specifieke segment: PSEG0000, PSEG4000 en PSEG8000. Ze zijn -op respectievelijk pagina 0,1 en 2 aanschakelbaar. - -Heap - Blok geheugen in pagina 3 (ergens tussen &HC000 en -&HFFFF) waarvan MemMan toepassingsprogramma's een stuk aan -kunnen vragen en daarna vrij mogen gebruiken. - -FastUse - Zelfde als Use, maar dan het adres waarop de -routine direct aan te roepen is in pagina 3. - -UnCrash - Om te voorkomen dat segmenten aangevraagd zijn en -door een crash van een programma nooit meer vrij zouden -worden gegeven, voert de IniChk routine een unCrash uit. -Hierbij worden alle segmenten weer vrijgegeven. Het -unCrashen van een segment is te voorkomen door een segment -de Reserved status te geven. Dit kan met de functie SetRes -(11). Normaal gesproken hoeft een segment niet de Reserved -status gegeven te worden. - - - D E P R I N C I P E S - -MemMan verdeelt het aanwezige geheugen in segmenten van 16 -kB. Voordat een segment gebruikt mag worden moet het worden -aangevraagd. Na gebruik dient het weer te worden -vrijgegeven. Er zijn twee soorten segmenten: de zogenaamde -pagina-specifieke ofwel PSEG's en de flexibele FSEG's. - -PSEG's zijn segmenten die aangevraagd worden voor het -gebruik op een bepaalde pagina, bijvoorbeeld van -&h4000-&h7FFF of van &h8000-&hBFFF. Wanneer er een PSEG -aangevraagd wordt zal MemMan zo mogelijk geheugensegmenten -toewijzen die niet in een memory-mapper zitten. - -FSEG's zijn segmenten die op elke willekeurige pagina kunnen -worden ingeschakeld. Deze segmenten komen altijd uit memory -mappers. Welk soort segment er ook aangevraagd wordt, MemMan -zal een 16-bits 'segmentcode' teruggeven. Deze segmentcode -is weer nodig bij het inschakelen of het weer vrijgeven van -het segment. Wie alleen maar geheugen nodig heeft in het -gebied van &h8000 tot &hBFFF kan dus het beste PSEG's -aanvragen. MemMan gebruikt dan eerst zoveel mogelijk -geheugen uit de 'oude' 16- en 64 Kb modules en gaat dan de -mapper gebruiken. - -Met behulp van MemMan hoeft er dus nooit meer naar geheugen -gezocht te worden. Simpelweg een pagina aanvragen, gebruiken -en uiteindelijk weer vrijgeven. Zo eenvoudig is dat. - -Overigens is er een pagina die zich met MemMan niet laat -schakelen. Pagina 3 bevat behalve de MemMan code zelf ook de -stack (meestal) en een grote hoeveelheid systeemvariabelen. -Er zitten nogal wat haken en ogen aan het wegschakelen van -dat alles. - - - F U N C T I E O M S C H R I J V I N G - -MemMan functies kunnen worden uitgevoerd door een aanroep -van de `Extended BIOS' of EXTBIO hook, op adres &HFFCA. Het -device ID van MemMan - 'M' oftewel &H4D - moet in register D -worden geplaatst. Register E dient het MemMan functienummer -te bevatten. Na aanroep van een MemMan functie kunnen alle -registers gewijzigd zijn, behalve indien het tegendeel wordt -vermeld bij de functie-omschrijving. - -Omdat de EXTBIO hook gebruikt wordt voor diverse systeem -uitbreidingen zoals Kanji en RS232 interfaces, is het -mogelijk dat MemMan functie-aanroepen bijzonder langzaam -verwerkt worden. De prestaties van de MemMan -toepassingsprogramma's kunnen aanmerkelijk worden verhoogd -door functie afhandelingsroutine van MemMan rechtstreeks aan -te roepen, in plaats van de EXTBIO hook. Het adres waarop de -functie afhandelingsroutine aangeroepen kan worden, kan -worden opgevraagd via de info functie (50). - -De meeste MemMan functies bevinden zich in een apart -geheugensegment in pagina 1. Deze functies schakelen over op -een een interne stack, waardoor MemMan -toepassingsprogramma's met een betrekkelijk kleine stack -kunnen volstaan. Door een MemMan functie worden maximaal -twintig bytes op de stack van het toepassingsprogramma -geplaatst. Dit geldt echter alleen indien de functie -rechtstreeks, of via de MemMan functie-afhandelingsroutine -wordt aangeroepen. - -Een functie-aanroep via de EXTBIO hook kan echter een -bijzonder grote stack vereisen. Dit wordt veroorzaakt -doordat alle uitbreidings-modules die aan de EXTBIO hook -gekoppeld zijn elkaar aanroepen, net zo lang totdat ��n -module de functieaanroep herkent. Wanneer er tussendoor ook -nog interrupts afgehandeld worden, kan het stackgebruik -sterk oplopen. Al met al kan gesteld worden dat er bij een -aanroep van de EXTBIO hook minimaal 150 bytes stackruimte -beschikbaar moet zijn. - -Het is derhalve verstandig om via de info functie (50) het -adres op te vragen van de routine die de MemMan functie -aanroepen afhandelt. Wanneer deze routine vervolgens -rechtstreeks aangeroepen wordt, wordt de verwerkingssnelheid -verhoogd en blijft het stack-gebruik beperkt. - -De interruptstand blijft na een MemMan functie-aanroep in -meeste gevallen ongewijzigd. Sommige functies zoals de -diverse (Fast)Use functies schakelen de interrupts echter -uit. Wanneer een MemMan functie werd aangeroepen met de -interrupts uit, zal MemMan nooit terugkeren met de -interrupts ingeschakeld. - -Deze eigenschap is bijvoorbeeld van belang voor TSR -programma's die slechts een zeer kleine stack ter -beschikking hebben. Zo lang de interrupts uit staan, kunnen -alle MemMan functies zonder problemen worden uitgevoerd, -mits de functie verwerkingsroutine van MemMan rechtstreeks -wordt aangeroepen. Wanneer de interrupts echter aan staan is -een grote stack vereist, omdat de -interrupt-verwerkingsroutine enkele tientallen bytes op de -stack plaatst. - - -Naam : Use0 -Nummer : 0 -Functie: Aanschakelen van een segment op pagina 0 - (adresgebied 0000..3FFF) -In : HL = Segmentcode -Uit : A = Resultaatcode (-1 = Mislukt, 0 = Gelukt) - -Het inschakelen van een segment in pagina 0 is alleen -mogelijk indien het segment de MSX-standaard slot-schakel -entry points bevat. - -Opm: Deze functie mag niet worden aangeroepen via de EXTBIO -hook. Deze functie mag alleen worden uitgevoerd door een -rechtstreekse aanroep van de MemMan functie -afhandelingsroutine of de FastUse0 functie. De adressen -waarop deze routines aangeroepen kunnen worden, kunnen via -de info functie (50) worden verkregen. - - -Naam : Use1 -Nummer : 1 -Functie: Aanschakelen van een segment op pagina 1 - (adresgebied 4000..7FFF) -In : HL = Segmentcode -Uit : A = Resultaatcode (-1 = Mislukt, 0 = Gelukt) - -Opm: Deze functie mag niet worden aangeroepen via de EXTBIO -hook. Deze functie mag alleen worden uitgevoerd door een -rechtstreekse aanroep van de MemMan functie -afhandelingsroutine of de FastUse1 functie. De adressen -waarop deze routines aangeroepen kunnen worden, kunnen via -de info functie (50) worden verkregen. - - -Naam : Use2 -Nummer : 2 -Functie: Aanschakelen van een segment op pagina 2 - (adresgebied 8000..BFFF) -In : HL = Segmentcode -Uit : A = Resultaatcode (-1 = Mislukt, 0 = Gelukt) - -Opm: Deze functie mag niet worden aangeroepen via de EXTBIO -hook. Deze functie mag alleen worden uitgevoerd door een -rechtstreekse aanroep van de MemMan functie -afhandelingsroutine of de FastUse2 functie. De adressen -waarop deze routines aangeroepen kunnen worden, kunnen via -de info functie (50) worden verkregen. - - -Naam : Alloc -Nummer : 10 -Functie: Aanvragen van een segment -In : B = Segment voorkeuze code -Uit : HL = Segmentcode. (0000 = Geen segment meer vrij) - B = Segmentsoort code (-1 = FSeg, 0 = PSeg) - -Segment voorkeuze code overzicht (Register B): - -Bit 7 6 5 4 3 2 1 0 -^ ^ ^ ^ ^ ^ ^ ^ -| | | | | | | | -| | | | | | +-+--> Segment Type. 00 = PSEG0000 -| | 0 0 0 0 01 = PSEG4000 -| | 10 = PSEG8000 -| | 11 = FSEG -| +--------------> 1 = Prefereer TPA oftewel het -| standaard MSXDOS RAM slot -+----------------> 1 = Prefereer onge�xpandeerd (dus - snel) slot - -De bits 5 tot en met 2 zijn niet gebruikt en moeten 0 zijn. - -Mocht een PSEG type aangevraagd, maar niet beschikbaar zijn -wordt - indien mogelijk - een FSEG ter beschikking gesteld -die dan het PSEG kan vervangen. - - -Naam : SetRes -Nummer : 11 -Functie: Segment de Reserved status geven -In : HL = Segmentcode - -Geeft een segment de `Reserved-status'; zodat het segment -niet automatisch wordt vrij gegeven na aanroep van de IniChk -routine. Normaal gesproken hoeven programma's de reserved -status niet te zetten, behalve als een programma - -bijvoorbeeld een Ramdisk - een segment voor eigen gebruik -zeker wil stellen. - - -Naam : DeAlloc -Nummer : 20 -Functie: Teruggeven van een segment -In : HL = Segmentcode - -Bij het verlaten van een programma dient deze functie -gebruikt te worden om alle aangevraagde segmenten weer terug -te geven aan MemMan. De eventuele reserved status van het -terug te geven segment wordt door DeAlloc automatisch -opgeheven. - -Segmenten die ook door DOS2 beheerd worden, worden door de -DeAlloc functie weer ter beschikking gesteld van DOS2. - - -Naam : ClrRes -Nummer : 21 -Functie: Reserved status van het segment opheffen -In : HL = Segmentcode - -Het is niet nodig deze functie vlak voor DeAlloc aan te -roepen. DeAlloc heft zelf de Reserved status van het segment -op. - - -Naam : IniChk -Nummer : 30 -Functie: Initialisatie MemMan voor een programma -In : A = Controle code -Uit : A = Controle code + "M" - DE = Versie nummer (format: Versie #D.E) - -Deze routine telt de ascii-waarde van de letter "M" op bij -de inhoud van register A. Hierdoor kan er een MemMan -aanwezigheids controle uitgevoerd worden. Verder wordt er -een unCrash uitgevoerd en worden de segmentcodes van de -actief aangeschakelde sloten berekend en opgeslagen voor -CurSeg. - -De IniChk functie mag slechts ��n keer door ieder MemMan -toepassings programma aangeroepen worden. Dit aanroepen van -IniChk dient te gebeuren voordat de overige functies van -MemMan aangroepen worden. TSR programma's mogen de IniChk -functie nooit aanroepen. - - -Naam : Status -Nummer : 31 -Functie: Status gegevens van MemMan ophalen -Uit : HL = Aantal aanwezige segmenten - BC = Aantal nog vrije segmenten - DE = Aantal segmenten in dubbel beheer bij DOS2 en - MemMan - A = Connected Status van de aangesloten hardware. - Bit Functie - 0 1=Dos2 Mapper Support Routines aanwezig - 1-7 Gereserveerd, altijd 0 - -Als bit 0 van de Connected status gezet is, zijn de -geheugenbeheer functies van DOS 2.20 aanwezig. - -Het aantal nog vrije segmenten kan lager zijn dan is -aangegeven in register BC, omdat sommige segmenten na de -installatie van MemMan door DOS2 gebruikt zijn - om -bijvoorbeeld een ramdisk te installeren. - -Naam : CurSeg -Nummer : 32 -Functie: Segmentcode van een aangeschakeld segment opvragen. -In : B = Paginanummer (0,1,2,3) -Uit : HL = Segmentcode -A = Segmentsoort code (255 = FSeg, 0 = Pseg) - -Deze routine geeft de huidige segmentcode terug van een van -de vier pagina's. - -TSR programma's mogen deze functie niet gebruiken om het -actieve segment in geheugen pagina 0 te bepalen. Om tijd te -sparen wordt deze stand niet automatisch bepaald en -opgeslagen bij de aanroep van een TSR. De actieve segmenten -in de pagina's 1 en 2 worden echter bij iedere hook-aanroep -opnieuw bepaald en kunnen ten alle tijde via deze functie -opgevraagd worden. Omdat in pagina 3 altijd hetzelfde -segment actief is, is ook de segmentcode van pagina 3 altijd -opvraagbaar. - -Een snellere variant van deze functie is FastCurSeg routine. -gebruikt. Het adres waarop deze routine aangeroepen kan -worden is via de Info functie (50) op te vragen. - - -Naam : StoSeg -Nummer : 40 -Functie: Huidige segmenten stand opslaan -In : HL = Buffer adres (9 bytes groot) - -De voor MemMan bekende segmentcodes van de actief -aangeschakelde sloten worden opgeslagen in het buffer. Deze -segmentcodes zijn in beginsel door IniChk berekend en later -door de Use functies geupdate. De opgeslagen stand is niet -de huidige stand, maar de voor MemMan bekende stand. TSR -kunnen hiermee dus niet de actieve stand opslaan. - -Opm: Deze functie mag niet worden aangeroepen via de EXTBIO -hook. Deze functie mag alleen worden uitgevoerd door een -rechtstreekse aanroep van de MemMan functie -afhandelingsroutine. Het adres waarop deze routine -aangeroepen kan worden, kan via de info functie (50) worden -verkregen. - -Natuurlijk kunnen ook de (Fast)CurSeg functies gebruikt -worden om de momentele segment-stand op te vragen. - - -Naam : RstSeg -Nummer : 41 -Functie: Opgeslagen segment-stand actief maken -In : HL = Buffer adres - -De in het buffer opgeslagen segment-stand wordt weer actief -gemaakt en wordt opgeslagen voor CurSeg. - -Opm: Deze functie mag niet worden aangeroepen via de EXTBIO -hook. Deze functie mag alleen worden uitgevoerd door een -rechtstreekse aanroep van de MemMan functie -afhandelingsroutine. Het adres waarop deze routine -aangeroepen kan worden, kan via de info functie (50) worden -verkregen. - -Natuurlijk kunnen ook de (Fast)Use functies gebruikt worden -om een segment-stand te herstellen. - - -Naam : Info -Nummer : 50 -Functie: Geeft informatie over onder andere aanroep-adressen -van MemMan functies -In : B = Informatie nummer (0..8) -Uit : HL = Informatie - -Informatie nummer overzicht. Tussen haakjes staan de -equivalente MemMan functie codes: - -0 - Aanroepadres van FastUse0 (functie 0) -1 - Aanroepadres van FastUse1 (functie 1) -2 - Aanroepadres van FastUse2 (functie 2) -3 - Aanroepadres van TsrCall (functie 63) -4 - Aanroepadres van BasicCall -5 - Aanroepadres van FastCurSeg (functie 32) -6 - Aanroepadres van MemMan, de functie-afhandelingsroutine -7 - Versienummer van MemMan, format: Versie #H.L -8 - Aanroepadres van XTsrCall (functie 61) - -De bovengenoemde functie-adressen mogen door een -toepassingsprogramma of TSR rechtstreeks aangeroepen worden. -Alle entry adressen liggen gegarandeerd in pagina 3. - -De functies worden snel uitgevoerd omdat de MemMan CALL naar -de EXTBIO hook vervalt en de functie-codes in registers D en -E niet uitgeplozen hoeven worden. Een ander voordeel is dat -parameters ook via het register DE doorgegeven kunnen -worden, dit is vooral van belang bij de TsrCall en BasicCall -functies. - -Bijvoorbeeld, de initialisatie routine van een TSR kan de -benodigde functieadressen via de INFO functie opvragen en -deze vervolgens voor later gebruik in de TSR programmacode -opslaan, wat de snelheid van het TSR programma zeer ten -goede kan komen. - -Een exacte beschrijving van de bovenstaande functies kan -gevonden worden bij de MemMan functie waarvan het nummer -tussen haakjes is aangegeven. - -Houd echter onder de aandacht dat de `snelle' functies op de -volgende punten van de gewone MemMan functies verschillen: - -fastUse0-2: Schakelt een segment in in een bepaalde geheugen -pagina. Zie de omschrijving bij de memMan `Use' functies. - -tsrCall: Register [DE] wordt ongewijzigd aan de TSR -doorgegeven. Dit in tegenstelling tot functie 63 (TsrCall), -register DE is dan al bezet om het MemMan functienummer in -op te slaan. - -xTsrCall: Alle mainregisters (AF,HL,BC,DE) worden -ongewijzigd aan de TSR doorgegeven. De TSR-ID code dient in -register IX te worden geplaatst. - -basicCall : Heeft geen MemMan functie nummer. - Functie: Aanroepen van een routine in de BASIC - ROM. - In: IX = Call address in pagina 0 of 1 - AF,HL,BC,DE = dataregisters voor de - BASIC-ROM - Uit: AF,HL,BC,E = dataregisters van de - BASIC-ROM - Interrupts disabled - -Via deze functie kunnen TSR's een routine aanroepen die zich -in pagina 0 en/of pagina 1 van het BASIC-ROM bevindt. De -bios moet al in pagina 0 aangeschakeld zijn. In pagina 1 -wordt de BASIC ROM door MemMan aangeschakeld. - -Dit is bijvoorbeeld noodzakelijk om de math-pack routines -aan te kunnen roepen die in pagina 0 van de BASIC ROM -zitten, maar tussendoor ook een aantal routines in pagina 1 -aanroepen. - -De H.STKE (stack error) hook wordt afgebogen, zodat na een -eventueel op getreden BASIC error de interne stacks van -MemMan gereset kunnen worden. - -fastCurSeg: In register [A] komt geen zinnige waarde terug. -De MemMan CurSeg functie (32) geeft aan of het een FSEG/PSEG -betreft. - -memMan: Heeft geen MemMan functienummer - Functie: Rechtstreeks aanroepen van een MemMan - functie. - In: E=MemMan functienummer - AF,HL,BC = Dataregisters afhankelijk - van de aan te roepen functie. - Uit: AF,HL,BC,DE = dataregisters afhankelijk - van de aangeroepen functie. - -Een aanroep van deze routine heeft hetzelfde effect als het -aanroepen van een MemMan functie via de EXTBIO hook. Doordat -echter de aanroep naar de EXTBIO hook vervalt, worden de -overige uitbreidingen die aan deze hook gekoppeld zijn niet -aangeroepen. Hierdoor blijft het stack gebruik beperkt en -wordt de verwerkingssnelheid verhoogd. - - -Naam : XTsrCall -Nummer : 61 -Functie: Roep het driver-entry van een TSR aan -In : IX = ID code van de aan te roepen TSR -AF,HL,DE,BC worden ongewijzigd doorgeven aan de TSR. -Uit : AF,HL,BC,DE komen ongewijzigd terug van de TSR. - -Deze functie is een verbeterde versie van de functie TsrCall -(63). Omdat met deze functie alle main-registers aan de TSR -kunnen worden doorgegeven, verdient het aanbeveling om deze -functie te gebruiken in plaats van functie 63. - -Opm: Deze functie mag niet worden aangeroepen via de EXTBIO -hook, omdat bij een aanroep via EXTBIO het IX-register -verminkt wordt. Roep deze functie daarom rechtstreeks aan, -of gebruik de MemMan functie-afhandelingsroutine. De -adressen waarop deze routines aangeroepen kunnen worden, -kunnen via de info functie (50) worden opgevraagd. - - -Naam : GetTsrID -Nummer : 62 -Functie: Bepaal TSR ID code -In : HL = Pointer naar de TsrNaam (12 tekens). - Ongebruikte posities opvullen met spaties. -Uit : Gevonden: Carry clear (NC) - BC = TSR ID code -Anders : Carry set (C) - - -Naam : TsrCall -Nummer : 63 -Functie: Roep het driver-entry van een TSR aan -In : BC = ID code van de aan te roepen TSR -AF,HL,DE worden ongewijzigd doorgeven aan de TSR. -Uit : AF,HL,BC,DE komen ongewijzigd terug van de TSR. - -Merk op dat alhoewel het DE register ongewijzigd aan de TSR -wordt doorgegeven, het niet voor parameter-invoer benut kan -worden. De Extended BIOS functiecode van MemMan (D='M' E=63) -moet namelijk in dat register geplaatst worden. - -Bij de Fast-TsrCall routine treedt deze complicatie niet op; -het adres van deze routine kan middels de info functie -opgevraagd worden. - - -Naam : HeapAlloc -Nummer : 70 -Functie: Alloceer ruimte in de heap -In : HL = Gewenste grootte van de ruimte (in bytes) -Uit : Genoeg ruimte: HL = Startadres van de ruimte -Anders : HL = 0000 - -Door middel van deze functie kan een stuk geheugen -gealloceerd worden. Het geheugenblok zal zich gegarandeerd -in pagina 3 bevinden. - -De heap is vooral nuttig voor TSR programma's, die hem -bijvoorbeeld als tijdelijke of permanente diskbuffer kunnen -gebruiken. Ook andere buffers - waarvan het absoluut -noodzakelijk is dat ze zich in pagina 3 bevinden - kunnen op -de heap worden geplaatst. - -Aangevraagde blokken geheugen uit de heap blijven -onbruikbaar voor andere programma's totdat een `HeapDeAlloc' -is uitgevoerd (functie 71). - -De grootte van de heap kan worden ingesteld door middel van -het configuratie programma CFGMMAN. - - -Naam : HeapDeAlloc -Nummer : 71 -Functie: Geef geAlloceerde ruimte van de heap weer vrij -In : HL = Startadres van de ruimte - - -Naam : HeapMax -Nummer : 72 -Functie: Geef de lengte van het grootste vrije blok geheugen -in de heap terug -Uit : HL = Lengte van het grootste vrije blok - - -D E S T A C K O N D E R M E M M A N - -MemMan toepassingsprogramma's dienen de stack pointer (SP) -bij voorkeur in pagina 2 of 3 (tussen &h8000 en &HFFFF) te -plaatsen. Indien MemMan door een hook-aanroep geactiveerd -wordt, wordt het huidige segment in pagina 1 (&h4000 tot -&h8000) namelijk weggeschakeld om plaats te maken voor de -TSR-Manager en de eventuele TSR's. Indien de stack zich op -dat moment in pagina 1 bevindt zal de computer vastlopen. - -Indien TSR's na een BDOS call of interrupt via een BIOS-hook -worden aangeroepen treden geen stackproblemen op; ook niet -indien de stack van het toepassingsprogramma in pagina 1 -staat. De BDOS en interruptfuncties gebruiken namelijk hun -eigen stack in pagina 3. De stack bevindt zich dan alsnog in -pagina 3 op het moment dat de hook aangeroepen wordt. - -Bestaande CP/M en MSX-DOS programmatuur is dus zonder -problemen in combinatie met MemMan 2 te gebruiken - maar -alleen indien de standaard BDOS calls gebruikt worden. -Wanneer echter via een interslot call een BIOS routine -rechtstreeks aangeroepen wordt, dient de stack in pagina 2 -of 3 te staan. Reserveer in dat geval minimaal 150 bytes -voor de stack. - - -Appendix 1: BIOS aanroepen onder Turbo Pascal - -Indien in een Turbo Pascal programma interslot-calls naar de -BIOS gebruikt worden, is het belangrijk dat de stack in -pagina 2 of 3 staat. Op het moment dat de BIOS dan een hook -aanroept kan MemMan veilig de TSR's aktiveren. De positie -van de stack is afhankelijk van het maximum programma adres -dat tijdens de compilatie in Turbo Pascal is ingesteld. De -stack bevindt zich in Turbo Pascal direkt onder het -variabelen geheugen. Het variabelen geheugen dient bij -programma's die de BIOS aanroepen dus ruim boven adres -&h8000 geplaatst te worden. - -Is geen source voorhanden, dan is het mogelijk om met een -debugger het stack adres van Turbo Pascal programma's aan te -passen. De initialisatie code van een TP programma ziet er -als volgt uit: - -start: jp init -... -... -init: ld sp,100h -ld hl,nn -ld de,nn -ld bc,nn -call yy -ld hl,nn -ld de,stack ;DE bevat het stack adres, hoeft -ld bc,nn ; alleen aangepast te worden als het -call zz ; lager is dan &h80A0 -... - -Het stackadres in register DE kan bijvoorbeeld op &hC100 -gezet worden. diff --git a/Sunrise Special/1/Muis uitlezen.md b/Sunrise Special/1/Muis uitlezen.md deleted file mode 100644 index 1618c36..0000000 --- a/Sunrise Special/1/Muis uitlezen.md +++ /dev/null @@ -1,216 +0,0 @@ -# M U I Z E N I S S E N - - -Het valt me telkens weer op dat er op MSX maar weinig -gebruik gemaakt wordt van de muis. Dit in tegenstelling tot -andere systemen waar de muis een absolute noodzaak is -geworden. Het is dan ook een heel slim apparaatje dat een -gigantische brug kan slaan tussen de software en de -gebruiker. Het is toch fantastisch dat er zo'n doosje is dat -als je het beweegt een gelijksoortige beweging van een -voorwerp op het scherm teweeg brengt! - - -## D E G E S C H I E D E N I S - -De muis is ��n van de belangerijkste computerontwikkelingen -van de afgelopen 15 jaar. Voorheen moesten alle commando's -domweg ingetikt worden en dat maakte de computer niet echt -toegankelijk voor het grote publiek omdat de besturing van -die dingen alleen maar door een klein elitair groepje mensen -gedaan kon worden. Daar is met de komst van de muis nu een -radikaal einde aan gekomen. De muis is zelfs zo 'makkelijk' -dat een kind dat nog maar amper praten al met een computer -overweg kan omdat de besturing zo eenvoudig is geworden. - -De muis op zich is niet duur, maar de verdere (grafische) -weergave bleek ontzettend duur te zijn. Daar kwam pas -verandering in toen computers goedkoper werden omdat de -produktie omhoog ging. Plotseling werden massaal video -kaarten (en losse VDP's) gemaakt die de muis nu ook voor het -grote publiek toegankelijk maakten. - - -## D E M U I Z E N V A N N U - -Nu, zoveel jaar later kost een muis niet meer dan 150 -gulden. Er zijn muizen in alle soorten en maten en er is -gelukkig een zekere standarisatie van aansluiting. -Natuurlijk had IBM in haar oneindige wijsheid besloten om de -zaken zo aan te pakken dat er een behoorlijke connector voor -nodig is om een muis aan een PC te hangen, maar er waren -gelukkig ook verstandige mensen die de muis gewoon aan de -bekende 'Joystick' poort connector gehangen hebben. - -Bij mijn weten gebruiken MSX, Amiga en Atari deze connector -en ze zijn ook volledig uitwisselbaar (alhoewel de standaard -meegeleverde muizen van de laatste twee matig tot slecht van -kwaliteit zijn). - -## D E W E R K I N G - -Er zijn ruwweg 3 soorten muizen, waarvan er twee weer op -elkaar lijken, nl: -- de elektro mechanische muis -- de opto mechanische muis -- de optische muis - -De eerste vorm is meteen ook de oudste en gebruikt het -overbekende 'balletje tegen asje' systeem. Aan die twee -assen zitten echter twee pot-meters (variabele weerstand) -die 360 graden kunnen draaien. Door nu de weerstand te meten -kon de positie van de muis berekend worden. Deze vorm had -echter als nadeel dat het balletje makkelijk over de as -gleed waardoor de as niet draaide. Dit slippen werd weer -veroorzaakt doordat de pot-meter teveel wrijvingsweerstand -genereerde. Verder sleten de pot-meters snel waardoor de -weerstandsmeting niet meer goed ging. Deze muizen worden -tegenwoordig niet meer gemaakt en wie er ��n heeft moet dat -ding maar in de kast leggen, want het kon wel eens een -museumstuk worden. - -De tweede soort muis is de meest gebruikte muis, en werkt -precies hetzelfde als de eerste vorm met het verschil dat de -pot-meters vervangen zijn door twee 'wieltjes' met gaten. -Affijn, omdat de meeste mensen de rest van de werking wel -weten zal ik er verder geen woorden over vuil maken. Het -voordeel van deze muis boven de eerste is dat hij niet slijt -en dat er heel weinig wrijvingsenergie op de asjes komt. - -Deze eerste twee vormen hebben echter een gezamelijk nadeel; -als ze vuil worden gaan ze haperen (oftewel wrijving). Dit -nadeel is opgelost met de komst van de volgende generatie -muizen, de optische muis. Deze muis heeft geen bewegende -onderdelen en wrijving heeft dus geen invloed op de -prestaties. Het komt er op neer dat er in de muis een -lichtje brandt samen met een element dat licht opvangt. De -muis wordt bewogen over een mat met horizontale en vertikale -lijnen die licht weerkaatsen. Affijn, als het licht -weerkaatst vangt het andere element het op en zo herkent de -muis dat hij beweegt. - -Al deze muizen werken echter wel met het principe dat ze -verplaatsing meten en niet plaats. Ze leveren dus de -afgelegde afstand tussen twee metingen aan de computer af -die deze meting dan in een positie omzet. Dit gebeurd door -de afstand bij de vorige positie op te tellen. - - -## D E M U I S L E E S A K T I E - -Er is in het verleden nogal wat verwarring geweest over de -vraag hoe een MSX2 de muis leest omdat de VDP van een MSX2 -een hardwarematische muisleesroutine bevat, die echter niet -gebruikt wordt. De twee joystickpoorten zitten op alle -MSX'en aan register 14 en 15 van de PSG en de VDP heeft er -geen bal mee te maken. - -Om een komplete leesaktie te doen is nogal wat nodig omdat -de muis maar de beschikking heeft over een 4 bits databus. -Om dus 2 keer een 8 bits offset te lezen (X en Y) moet er -dus 4 keer gelezen worden waarbij de muis eerst verteld moet -worden dat er gelezen gaat worden. Aan de hand van de -routine (GTMOUS) zal ik nu het algoritme verklaren. - -We nemen even aan dat de muis in poort 1 zit. In dat geval -staat in (PORT) de waarde 10111111B en in (PORT+1) de waarde -00010000B - -GTMOUS: -- Lees PSG register 15 -- Wis bit 6, dit geeft aan dat de muis in poort 1 zit -(Zet bit 6 om aan te geven dat de muis in poort 2 zit) -- Zet bit 4, zodat de muis weet dat nu XH klaargezet moet -worden. Bit 5 doet hetzelfde voor poort 2 -Opm: XH/YH = Bit 4-7 van X/Y offset -XL/YL = Bit 0-3 van X/Y offset -- Wacht even op muis (het is een relatief traag ding) -- Lees XH (Verdere details volgen) -- Lees XL -- Lees YH -- Lees YL -Dit lezen is niet eenvoudig omdat de muis niet automatisch -weet wanneer ��n van de waarden gelezen is. Om aan de muis -te vertellen dat je de waarde gelezen hebt, moet bit 4 -(indien de muis in poort 2 zit bit 5) van PSG register 15 -ge�nverteerd worden. Als tijdens de volgende leesaktie -register 15 weer geschreven wordt zal de muis dit -ge�nverteerde bit zien waarop het beestje de volgende te -lezen waarde op zijn 4 bits databus zet. Na een kleine -wachttijd wordt deze waarde dan uit register 14 gelezen. - - -## E E N M U I S B E S T U R I N G S P R O G R A M M A - -Laat ik beginnen met het bedanken van Stefan Boer die het -basisprogramma voor de muisbesturing heeft gemaakt waar ik -op voortgeborduurd heb. - -De routine is vrij universeel en werkt gegarandeerd op alle -MSX'en (vanaf MSX2). Als uitvoer zal een sprite op het -scherm getekend worden die de beweging van de muis volgt. -Wat meteen opvalt is dat het programma nogal groot is -geworden, maar dat komt omdat er maar heel weinig BIOS calls -gebruikt worden. De muisroutine van de MSX2 en turbo R staat -nl. in een subslot en dat maakt de routine relatief traag. -Voor de meeste routines is dit niet zo'n bezwaar, maar als -een routine vaak aangeroepen wordt is het toch wel handig -dat alles zo vlot mogelijk verloopt. - -Verder bevat het programma een schat aan andere nuttige -informatie. Wat dacht je bv. van de vuurknop uitleesroutine -die feitelijk een kopie is van de routine die in de -interruptafhandelingsroutine van FD9FH staat. Deze routine -kijkt naar alle vuurknoppen (0 t/m 5) en doet dit 5 keer zo -snel als de BIOS routine omdat je die in dit geval 5 keer -aan zou moeten roepen. In principe is deze routine overbodig -omdat er in het systeem RAM ook een byte is waar de huidige -vuurknop status in staat, maar ik heb hem er toch bij gezet -omdat er onder MSX programmeurs de trend bestaat om het hele -systeem plat te leggen zodat er geen processortijd verloren -gaat aan -voor hen- overbodige dingen en in dat geval wordt -dit byte niet meer gezet. - -Verder bevat het programma een routine die voor SCREEN 5, -page 0 twee sprites initialiseert en alle andere sprites weg -definieert. Je merkt het al, dit programma bevat meer dan -alleen maar een simpele muisbesturing. - - -## H O E W E R K T H E T ? - -Als het programma opgestart wordt zullen eerst de benodigde -sprites ge�nitialiseerd worden. Daarna zal naar een muis -gezocht worden (CHKPRT) die in de variabele (PORT & PORT+1) -aangeeft of en in welke poort de muis zich bevindt. Is geen -muis aangesloten dan zal de waarde 0 in (PORT) staan. Nu -wordt nog een interruptroutine ge�nstalleerd die bij elke -interrupt de sprites zal herplaatsen. - -Verder zal de routine ook altijd met de cursorkeys werken -(logisch nietwaar??). Het uiteindelijke resultaat is dus -een hele snelle routine die zelf wel uitzoekt of en waar een -muis is aangesloten en die zowel met muis als met de -cursorkeys tegelijkertijd een 'arrow' over het scherm kan -bewegen in een van tevoren opgegeven venster. - -Een ander leuk detail is dat de muisroutine op zich ook op -MSX1 werkt, maar dat dan wel de muisplaats en initialiseer -routines herschreven moeten worden. - -Voor meer informatie over het hoe en wat van sprites moet ik -jullie naar ��n van mijn eerdere artikelen verwijzen die op -de GENIC ClubGuide Special #2 staat. - -Het programma staat los op deze disk (hoop ik) en heet -MOUSE.ASC Als u niet zo'n ster bent in het bedienen van een -assembler kunt u ook gewoon het programma MOUSE.BIN -opstarten. - -Ik hoop dat ik wat duidelijkheid heb gebracht in de wereld -van MSX muizen en natuurlijk wil ik in de toekomst een -stormvloed van programma's zien die de muis gebruiken, dat -spreekt voor zich (ik bedoel dus dat ik hoop dat dit muisje -nog een staartje krijgt). - -Alex van der Wal diff --git a/Sunrise Special/1/Pointers in Pascal.md b/Sunrise Special/1/Pointers in Pascal.md deleted file mode 100644 index d415749..0000000 --- a/Sunrise Special/1/Pointers in Pascal.md +++ /dev/null @@ -1,178 +0,0 @@ -#P O I N T E R S - - -Ik wil in dit stukje wat uitleg geven over pointers; wat kun -je er zoal mee doen, hoe ga je er mee om. Ik ga in principe -uit van een de taal Pascal, maar dit verhaal is met wat -fantasie om te zetten naar bijvoorbeeld machinetaal of -BASIC. - - -## W A T I S E E N P O I N T E R - -Een pointer is in feite een adres en op dat adres staat de -inhoud van een variabele. De variabele waar een pointer naar -wijst is meestal alleen via deze pointer toegankelijk. Om -het allemaal moeilijk te maken kun je ook nog pointers naar -pointers (naar pointers naar pointers enz.) hebben. - - -## W A A R O M P O I N T E R S G E B R U I K E N - -Voor het structureren van 'gelijksoortige data-elementen' -(dus bv. integers, arrays, bytes, records) zijn er in Pascal -in principe 3 mogelijkheden: de array, de file en pointers. - -De file is vooral bedoeld als in- en uitgangsmedium en niet -in de eerste plaats voor interne verwerking (daarvoor zijn -de mogelijkheden gewoon te klein). - -Arrays van een bepaald type bieden wel ruime verwerkings- -mogelijkheden, maar er kleven ook een aantal bezwaren aan, -waarvan de belangrijkste is dat we verplicht zijn de array -in een preciese omvang te declareren (bijvoorbeeld -array[1..100] of byte; deze array heeft een vaste omvang van -100 bytes), terwijl de omvang van de omvang van de rij die -in de array moet komen bijna nooit van te voren bekend is. -Hierdoor is bijna altijd de array te groot of te klein. - -Pascal biedt nog een andere structureringsmogelijkheid en -wel door middel van pointers. Hierbij zijn geen van de bij -de file en array genoemde bezwaren van toepassing. Aan -pointers kleven echter weer andere bezwaren, o.a. dat het -netwerk van pointers waarmee je werkt soms enorm complex kan -worden, maar aan de andere kant zijn er ook erg veel -voordelen. - - -## D E S P E L R E G E L S - -* TYPE-DEFINITIE -Een pointer-type wordt in pascal als volgt gedefinieerd: - - = ^ - -Voorbeeld: -type arint = array[1..100] of integer; -rek = record -a : integer; -x, y : byte; -z : array[1..24] of char -end; -PTRint = ^integer; -PTRari = ^arint; -p_rek = ^rek; - - -* POINTER-VARIABELE -We kunnen nu pointer-variabelen declareren aan de hand van -de zojuist gemaakte type-definities. - -Voorbeeld: -var p1, p2, p3 : PTRint; -p4, p5 : p_rek; - -Het bovenstaande creeert de pointers (zoals var ook alle -andere variabelen creeert). Een pointer heeft op een -MSX-computer een 'grootte' van 2 bytes, want daarin past -precies het gehele geheugen- bereik van 64 kB. - -* POINTER-OPERATIES -Er zijn drie manieren om aan een pointer-variabele een -waarde te geven: -- Met de standaard-procedure NEW. -Aanroep: NEW(p), waarbij p de betreffende -pointer-variabele is. - -Door de aanroep van NEW(p) wordt er in het geheugen van -de computer ruimte gereserveerd ter grootte van het -data-type waarnaar de pointer wijst. Als ik dus een -pointer naar een byte heb (^byte) dan wordt er dus ook -werkelijk 1 byte geheugen vrijgemaakt voor dat byte. - -Na de NEW-instructie kun je de pointervariabele een -waarde geven. Dit gaat bijna zoals bij iedere andere -variabele; via de pointer geef je de pointer variabele -nu een waarde. -scrijfwijze: ^ := - -Voorbeeld: -NEW(p1); { maak ruimte voor p1^ } -p1^ := 25; { geef pointervariabele p1^ de waarde 25 } - -- We kunnen een pointer-variabele ook de waarde geven van -een andere pointer-variabele via een assignment: Stel p1 -en p2 zijn pointers naar hetzelfde type pointer- -variabele (dit is erg belangrijk). Met p2 := p1 laat je -deze poinbters naar dezelfde variabele wijzen. p1 en p2 -zijn nu dus verschillende aanduidingen voor dezelfde -variabele... - -Er is een groot verschil tussen: -1) new(p1); 2) new(p1); -p1^ := 25; p1^ := 25; -new(p2); p2 := p1; -p2^ := 25; - -Er geldt na afloop: -1) p1^ = p2^ 2) p1^ = p2^ -twee variabelen een variabele -p1 <> p2 p1 = p2 - -- De derde mogelijkheid is om de pointer de waarde nil te -geven; hij wijst dan nergens naar. - -Voorbeeld: -p1 := nil; - - -Een gecreeerde variabele kunnen we ook weer vernietigen en -wel met de standaard-procedure DISPOSE. - -Voorbeeld: -dispose(p); - -Hierna is de variabele p^ vernietigd; de geheugenruimte -die door deze variabele bezet werd is weer vrijgegeven en -is dus weer beschikbaar. De pointer p is ongedefinieerd. - - -## T E N S L O T T E - -Je kunt met pointers leuke dingen uithalen. Zo kun je -bijvoorbeeld een 'gelinkte lijst' opzetten. Dit is een -array-achtig iets, waarbij je echter geen indexen en geen -vaste omvang hebt (wat je bij een array juist wel hebt). Je -creeert een record waarin een pointer zit die naar 'zijn -eigen' record wijst. - -Hierbij krijg je echter een kip-en-ei-probleem: als ik eerst -de pointer definieer, dan is het record nog niet bekend maar -als ik eerst het record definieer dan heb ik weer geen -pointer om naar dat record te laten wijzen. - -Dit is in pascal de enige toestand waarbij je een pointer -mag definieren naar een nog (!) niet-bestaand type. - -De definitie van de data-typen ziet er bijvoorbeeld zo uit: -type PTRrek : ^rek; { pointer naar type rek } -rek : record -A : array[1..7] of byte; -B : boolean; -next : PTRrek; { pointer naar het volgende - element in de lijst } -end; - -var startpunt, huidig : PTRrek; -^ ^ -| | -| +-- op deze plek in de lijst ben ik nu -| -+------------- eerste element uit de lijst (de 'wortel') - - -Bij lijsten wordt de waarde NIL gebruikt om het einde van de -lijst aan te geven (je moet de pointer(s) zelf die waarde -geven; standaard staat er alleen onzin in). - -Rudy Oppers diff --git a/Sunrise Special/1/Recursief programmeren.md b/Sunrise Special/1/Recursief programmeren.md deleted file mode 100644 index 7997be8..0000000 --- a/Sunrise Special/1/Recursief programmeren.md +++ /dev/null @@ -1,150 +0,0 @@ -# R E C U R S I E F P R O G R A M M E R E N - - -Dit is een onderwerp waar de gemiddelde MSX'er niet veel van -zal weten, maar dat toch buitengewoon interessant is. Het is -een programmeertechniek die al ontwikkeld is voordat het in -werkelijkheid gebruikt kon worden (lees: computers genoeg -geheugen hadden). - - -## D E T E C H N I E K - -Een recursieve routine is een routine die zichzelf aanroept. -Dit klinkt mischien een beetje vreemd, maar het is best -handig. Je zou je een routine voor kunnen stellen die op een -gegeven moment gegevens nodig heeft die met dezelfde routine -gevonden kunnen worden. - -Een voorbeeld: - -Stel je hebt een touw dat x meter lang is en je wilt dit -touw in stukjes van 1 en 2 meter gaan verdelen. De vraag is -nu op hoeveel manieren dit kan bij een gegeven x. - -Bij een lengte x=20 meter is dit al heel moeilijk te vinden, -maar bij een lengte van 2 meter is het aantal manieren -gelijk aan x, nl. 2. - -x = 2 meter => Manieren: 11 - 2 - Het kan dus op twee manieren. -x = 1 meter => Manieren: 1 - Het kan dus op 1 manier. - -Dit zijn twee gevallen waarbij het aantal manieren gelijk is -aan het aantal meter touw en dat is een heel belangerijk -gegeven. - -x = 4 meter => Manieren: 1111 - 112 - 121 - 211 - 22 - Het kan hier op 5 manieren. - -Met een beetje inzicht in getallen kan je afleiden dat het -aantal mogelijkheden bij x=4 gelijk is aan: - -Mog (x=4) = Mog.(x-2) + Mog.(x-1) - = 2 + 3 - = 5 - -Het aantal mogelijkheden bij x=3 is ook gelijk aan het -aantal meters lengte, maar dat is puur toevallig en verder -niet van belang. - -Wat we nu hebben gezien is dat we het aantal mogelijkheden -kunnen onderverdelen in deelprobleempjes en die op hun beurt -ook weer in deelprobleempjes, net zolang tot we een -deelprobleem hebben waarvan we het antwoord al weten. - -Nu is het mogelijk om dit in programmacode te schrijven. Ik -zal dat in de taal C doen omdat mijn PASCAL naar de -achtergrond is gezakt sinds ik met C werk. - -int aantal_mog(int x) -{ -if (x <= 2) /* Dit is de luie regel (zie verder) */ -return x; -else return aantal_mog(x-2) + aantal_mog(x-1); -} - -Dit stukje programma zal zelfs voor mensen die nog nooit een -regel C gezien hebben wel te begrijpen zijn. De parameters -die achter de 'return' opdracht staan zijn de parameters die -aan de vorige routine teruggegeven worden. In assembly -gebeurd dit met CALL en RET. - -De 'luie regel' is de regel die het werk in deelproblemen -verdeelt en die het vereenvoudigde probleem doorgeeft. Dit -programma is echter zo kort dat de luie regel meteen ook de -enige regel van de hele routine is. - -Het 'else' gedeelte geeft het deelprobleem door aan de -volgende routineaanroep. De 'return x' geeft een waarde van -x terug die we van tevoren al wisten (x <= 2). Ik kan het me -heel goed voorstellen als dit alles maar moeilijk te -bevatten is, maar het klopt toch allemaal echt. - - -## V O O R - E N N A D E L E N - -Het allergrootste voordeel van recursief programmeren is dat -het extreem weinig programmacode oplevert. Ik daag u graag -uit om dit probleem zonder recursie op te lossen. Het is -vast wel mogelijk, maar het wordt dan wel een heel lang -programma met heel veel sprongen en andere onoverzichtelijke -ellende. - -Nog een voordeel is dat zodra je recursie onder de knie hebt -(lees: zelf een paar keer doen) het heel eenvoudig is. De -probleemomschrijving lijkt nl. al heel veel op de feitelijke -programmacode en dus is het omzetten een makkie. - -Het grootste nadeel van recursie is dat - alhoewel de -routines zelf heel weinig geheugen nodig hebben - ze tijdens -executie enorme stukken werkruimte op kunnen slokken. In een -situatie waar je probeert om voor x=500 in te vullen zal je -wel begrijpen dat er extreem veel deelproblemen zullen -ontstaan die allemaal stackruimte nodig hebben om hun -terugkeeradres op te zetten. Zo heb je voor 10000 CALL -instrukties in assembly een stack nodig met een lengte van -20000 bytes en geloof me, dat haal je met deze methode -makkelijk. - -Dit is ook meteen de reden waarom ik niet een uitgewerkt -assembly programma gebruik. Het is op een MSX gewoon niet -praktisch omdat je meestal maar 64 kB direkt adresseerbaar -geheugen hebt waarvan meestal de helft voor het operating -system is en dan praten we nog niet eens over eigen -programma's. Dit artikel is daarom ook meer van informatieve -dan van praktische aard voor MSX omdat ook C op MSX een ware -ramp is (programmatechnisch gesproken dan). - - -## C O N C L U S I E - -Het zal sommige mensen wel niet aanstaan, maar voor dit -soort dingen heb je toch snel een PC of Atari nodig (werkt -heel lekker met C) omdat die veel meer direkt adresseerbaar -geheugen hebben en omdat die hardware veel geschikter is -voor een taal als C. Een recursie toepassing in assembly is -af te raden omdat dat behoorlijk moeilijk is terwijl je in C -feitelijk het probleem letterlijk over kunt tikken. - -Affijn, recursie is een heel interessante programmeermethode -met vele mogelijkheden zoals sorteren of het beheren en -onderhouden van boomstrukturen (waar ik ook nog wel eens -over kan schrijven omdat dat dingen zijn die prima in -assembly kunnen.) Een andere leuke toepassing van recursie -is bv. het probleem van de torens van Hanoi, maar dat is op -dit moment iets te ingewikkeld om hier te behandelen. - -Recursie is een veel gebruikte methode maar wordt voor de -meeste mensen pas interessant op het moment dat ze -professioneel met computers aan de gang gaan. Het is daarom -voor deze mensen gewoon leuk om alvast eens met deze -techniek in aanraking te komen. - -Alex van der Wal diff --git a/Sunrise Special/1/Rel assembleren.md b/Sunrise Special/1/Rel assembleren.md deleted file mode 100644 index 4b2f2e8..0000000 --- a/Sunrise Special/1/Rel assembleren.md +++ /dev/null @@ -1,173 +0,0 @@ -# R E L O C A T A B L E A S S E M B L E R E N - - -Eerst even dit: ik ga bij dit stukje uit van de GEN80 -assembler en de L80 linker. Omdat deze programma's onder DOS -draaien, gaat het hier dus ook automatisch over '.COM'-files -als resultaat. - -Naast GEN80 kun je bijvoorbeeld ook met M80 en RMAC reloca- -table assembleren. - - -## N O R M A A L A S S E M B L E R E N - -Veel mensen die wel eens iets in machinetaal doen, schrijven -hun listing als een lange lijst met instructies. Het -assembleren kan, vooral bij de wat grotere programma's, best -lang duren. De assembler moet immers die hele lap tekst van -een schijf lezen. - -Na het testen kom je er nog wel eens achter dat iets niet -helemaal goed werkt, en je gaat aan het foutzoeken... Na -lang zwoegen is de plaats waar de fout zich bevindt waar- -schijnlijk gevonden. Verandering aanbrengen en opnieuw -assembleren. - -De assembler moet nu die hele lap tekst (ook de foutloze -delen) opnieuw verwerken. Dit kost weer een hoop tijd. - -Dit proces herhaalt zich tot het moment dat de programmeur -denkt dat alle fouten uit het programma zijn verwijderd. - -Doordat iedere keer dat je de listing assembleert de hele -programmatekst moet worden verwerkt kan dit, vooral bij -lange listings, enorm veel tijd kosten. - - -## R E L O C A T A B L E A S S E M B L E R E N - -Maar het kan ook anders, en dat anders heet 'relocatable' -assembleren. - -Hierbij maak je gebruik van korte deelprogramma's -waarin allerlei subroutines staan. Die losse delen kun je -dan apart van elkaar assembleren en later aan elkaar plakken -met een linker (dit is een apart verkrijgbaar programma). - -In die losse delen zit de grote kracht van het relocatable -assembleren. Als je bij het foutzoeken een fout ontdekt, dan -hoef je niet weer die hele lijst door te spitten en te -assembleren, maar slechts een klein stukje van het hele -programma. Omdat je nu maar een stukje van het geheel door -de assembler haalt, bespaar je veel tijd (de andere modules -zijn immers niet veranderd, dus die hoef je nu dan ook niet -opnieuw te assembleren). - -Ook kun je met deze modulaire opzet modules die je eerder -hebt geschreven opnieuw gebruiken in je volgende program- -ma's. Je kunt zo dus een bibliotheek van kant en klare -modules opbouwen. - - -## W E R K W I J Z E - -Bij relocatable assembleren ga je er van uit dat een lang -programma op te splitsen valt in kortere delen, die als het -even kan ook nog min of meer iets met elkaar te maken hebben -(een soort van bibliotheek-bestanden dus). - -Als je een zo'n module geschreven hebt, dan kun je hem as- -sembleren. - -In de relocatable mode gaat een assembler heel anders om met -adressen. Hij ziet de adressen nu niet als een echt getal, -maar als een offset. De echte adressen worden pas later -ingevuld. - -Je krijgt nu ook geen '.COM'-files, maar '.REL'-files, wat -staat voor 'relocatable'. - -Na het schrijven van de modules en het assembleren ervan, -kun je alles aan elkaar gaan knopen, het 'linken'. Dit -linken gebeurt met een apart programma, de linker (bij- -voorbeeld LINK.COM of L80.COM). - - -## H E T L I N K E N - -Bij dit 'linken' geef je op welke modules je aan elkaar wilt -koppelen. Daarna geef je de naam van het uiteindelijke -programma op et voila! Je hebt je programma.... - -Met l80 gaat dit linken als volgt: - -A>l80 module1,module2,module3,prognaam/n/e - -De linker laadt nu de bestanden module1.rel, module2.rel en -module3.rel van disk. Ze komen ook in die volgorde in het -uiteindelijke programma te staan, dus je kunt niet zomaar -bij een module beginnen! In dit geval begint de programma- -uitvoer dus met module1. - -Hierna worden deze modules 'gelinkt'. Dit linken wil zoveel -zeggen als 'zet de genoemde bestanden achter elkaar en vul -waar dat nodig is de juiste adressen in'. Bij het invullen -van adressen worden al de 'offset' adressen vervangen door -absolute adressen. - -Na het linken wordt het gevormde programma op disk gezet. In -het voorbeeld is die naam 'prognaam.com'. Als er '/n' achter -achter een naam staat, gaat de linker er van uit dat dat de -naam van het programma moet worden. - -De '/e' wil zeggen dat de linker na het wegschrijven van -prognaam.com moet stoppen, zodat je weer in DOS zit. - - -## H E T R E S U L T A A T - -Nu heb je een programma op disk staan met de naam -prognaam.com. Het testen kan beginnen. Dit testen bestaat -meestal uit het opstarten van dat programma en proberen of -je je geesteskindje vast kunt laten lopen. - -Als er nu een fout wordt gevonden die bijvoorbeeld in -module2 zit, dan hoef je alleen module2 te veranderen en -opnieuw te assembleren. Bij het linken moet je (uiteraard) -wel weer alle modules opgeven. - -Het is trouwens handig als je de assembleeren link-opdracht -in een batchfile zet. Dat kan veel tikwerk schelen (en het -werkt wat vriendelijker). - -Zo'n batch ziet er dan bijvoorbeeld zo uit: - -gen80 %1 -l80 init,commando,diversen,edit,drawscr,getconv,monitor/n/e - - -## A S S S E M B L E R O P D R A C H T E N - -Een assembler die in een relocatable mode kan worden gezet, -kent een aantal speciaal op die mode gerichte opdrachten. - -Zo heb je bij GEN80 o.a. de directives external en public. -Er zijn er nog wel meer die met de relocatable mode te maken -hebben, maar dat staat allemaal in de handleiding van je -assembler. - -Je kunt GEN80 laten weten dat je in relocatable mode wilt -assembleren door op de eerste regel van je programma * R+ te -zetten. - -Het kan natuurlijk ook door gen80ins op te starten en die -relmode vast in het programma te zetten. Als je nu iets in -de absolute mode wilt assembleren, dan kun je dat doen door -op de eerste regel * R- te zetten. - - -## V O O R B E E L D - -Op deze disk staan als voorbeeld 3 modules (.GEN) en hun ge- -assembleerde vorm (.REL en .SYM). -De listings bevatten volop commentaar, dus bekijk ze eens... - -Ik heb ook het gelinkte programma bijgevoegd (RELADEMO.COM). -Het programma geeft een piepje, wacht op een toetsdruk en -drukt als laatste 20 keer het ingedrukte teken af. Op zich -niet echt nuttig, maar het gaat dan eigenlijk ook om de -listings. - - -Rudy Oppers diff --git a/Sunrise Special/1/Set scroll in basic.md b/Sunrise Special/1/Set scroll in basic.md deleted file mode 100644 index cf0c27a..0000000 --- a/Sunrise Special/1/Set scroll in basic.md +++ /dev/null @@ -1,108 +0,0 @@ -# S E T S C R O L L I N B A S I C - - - -## I N L E I D I N G - -Op een MSX2+ kan (in BASIC) m.b.v. het SET SCROLL commando -een vrijwel vloeiende scroll beweging krijgen. Omdat niet -iedereen zelf een vloeiende scroll in BASIC of in ML kan -programmeren, leg ik in deze tekst uit hoe je heel -gemakkelijk het SET SCROLL commando kunt gebruiken. - - -## S E T S C R O L L - -Het SET SCROLL commando kan je in alle schermen gebruiken, -behalve in SCREEN 0. Bij gebruik van het SET SCROLL commando -in SCREEN 0 gaat het naar boven scrollen niet hetzelfde als -in de grafische schermen. Bij deze tekstschermen gaat de -tekst of eventueel tekening niet omhoog maar scrollt met -rijen van acht hoog, (dat is dus het formaat van de ASCII -karakterset), daar wil ik mee zeggen dat alles wat boven aan -het blok van acht hoog verdwijnt, er aan de onderkant weer -bij komt. - -In de grafische schermen scrollt het hele beeld wel goed -maar krijg je het sprites-blok te zien. Daar heb ik wel een -truukje voor maar dat komt later. - - -## G E B R U I K - -Het gebruik is eigenlijk heel gemakkelijk, je hoeft namelijk -alleen het commando plus een getal voor de horizontale -scrolling en een getal voor de verticale scrolling in te -voeren. B.v. Set scroll 2,4 betekent dat je 2 pixels -horizontaal en 4 pixels verticaal scrollt. - -Overigens mag je geen negatieve (dus min) getallen in -voeren. Dat is ook niet nodig want als je in grafische -schermen SET SCROLL 0,0 in voert geeft dat het zelfde -resultaat als SET SCROLL 256,0 (voor SCREEN 6 en 7 dus SET -SCROLL 512,0), alleen is het scherm bij SET SCROLL 256 (of -512),0 een keer helemaal rond geweest. Zo kan je dus ook met -een lus optellen van 0 tot 255 (of 511) en ook aftellen van -255 (of 511) tot 0. Dat laatste geeft dus een scroll naar -links en de eerste naar -rechts. Zo werkt dat ook met het verticaal scrollen. - - -## V D P ( 1 9 ) E N V D P ( 2 4 ) - -Het set scroll commando komt overeen met VDP(19) (of set -adjust) en VDP(24). VDP(19) geeft namelijk een soort van -horizontale scroll net als set scroll X,0. Hier staat X voor -een getal. Er is wel een groot nadeel aan VDP(19) namelijk -dat de getallen die je in kunt voeren van -7 tot +8 lopen. -En met VDP(19) kan je een horizontale EN verticale scroll -maken. Dan nu VDP(24), dit komt volkomen overeen met het -getal dat je in voert bij set scroll voor verticaal -scrollen. Je kunt ook getallen van 0 tot 255 invoeren en -zelfs het spritesblok komt ook mee. Hieronder heb ik een -klein tabelletje neergezet waarin je kunt zien waarmee SET -SCROLL overeenkomt, zoals je ziet is verticaal scrollen -hetzelfde als VDP(24). - - HORIZONTAAL -- VERTICAAL -------------------------------------------------- -|SET SCROLL | GETAL 0 TOT 255 | GETAL 0 TOT 255 | -|-----------|-----------------|-----------------| -| VDP(19) | GETAL -7 TOT +8 | GETAL -7 TOT +8 | -|-----------|-----------------|-----------------| -| VDP(24) | N.V.T. | GETAL 0 TOT 255 | -------------------------------------------------- - - -## V O O R B E E L D - -Dan nu maar even een klein voorbeeld programaatje. Met de ' -geef ik wat kommentaar. Bedenk wel dat dit programmaatje -ALLEEN voor MSX2+ bedoeld is. -``` -; Dit programma is alleen voor grafische schermen 5 en 8 - -10 COLOR 15,0,0:SCREEN X ' VUL HIER VOOR X IN 5 OF 8 -20 SET PAGE 1,1:CLS:COPY (0,0)-(256,64) TO (0,212) -30 VDP(9)=VDP(9) OR 2 'LAAT DE SPRITES NIET ZIEN -40 OPEN "GRP:" FOR OUTPUT AS #1 -50 PSET (200,200):PRINT #1,"MSX 2+" -55 ' _TURBO ON 'GEBRUIK ALLEEN MET _BC -60 X1 = 1:Y1 = 1 -70 X2 = X2+X1:IF X2 > 245 THEN X1 = -1 'X2>245 ? JA,DAN -1 -80 Y2 = Y2+Y1:IF Y2 > 200 THEN Y1 = -1 'Y2>200 ? JA,DAN -1 -90 IF X2<15 THEN X1 = 1 'X2<15 ? JA,DAN +1 -100 IF Y2<50 THEN Y1 = 1 'Y2<50 ? JA,DAN +1 -110 SET SCROLL X2,Y2 'SCROLLEN -120 IF INKEY$="" THEN GOTO 70 ELSE END -``` -Je kan eventueel nog _BC gebruiken en dan in regel 55 het -rem (') teken weghalen. Als je het programma RUNt zie je de -tekst MSX 2+ over het beeld schuiven, de tekst gaat ook door -het beeld (dus links eruit en rechts erin). Maar er is geen -sprites blok te bekennen. - -Veel plezier met het SET SCROLL commando en misschien de -volgende keer een complete tekstzoek routine met scroll. - -Bart Schouten diff --git a/Sunrise Special/1/Te zachte PSG bij de NMS 8250 55 80.md b/Sunrise Special/1/Te zachte PSG bij de NMS 8250 55 80.md deleted file mode 100644 index a24da1c..0000000 --- a/Sunrise Special/1/Te zachte PSG bij de NMS 8250 55 80.md +++ /dev/null @@ -1,36 +0,0 @@ -# T E Z A C H T E P S G B I J D E N M S 8 2 5 0 / 5 5 / 8 0 - - -Vaak is het zo dat de PSG wegvalt door het gebruik van een -FM-PAK op de NMS 8250/55 en 80. Dit is jammer, want de -PSG-drums zijn vaak onmisbaar bij FM-PAK songs! - -Nu kan je dit probleem heel gemakkelijk oplossen. Men heeft -hier het kabeltje dat bij de PAK wordt geleverd voor nodig. -(van koptelefoon naar 1 tulpstekker). Druk nu de tulpstekker -in de monitor (AUDIO ingang) en de koptelefoon in de -buitenste uitgang van de FM-PAK, nu wordt de PSG door de -monitor gespeeld, maar de PAK muziek niet, deze zul je door -een versterker moeten laten weergeven. - -In mijn geval was dit een PSEUDO-STEREO versterker. Om de -PAK muziek door de versterker te laten klinken, heb je een -stekkerkabel nodig, met tenminste 1 tulpstekker, voor in de -AUDIO uitgang van de MSX. Aan de andere uiteinde zal een -stekker moeten zitten die in je versterker/installatie past. -Meestal is dit ook een tulpstekker (soms ook 2) - -Als alles goed is gegaan zal nu de PSG samen met de FM-PAK -te horen zijn, welliswar gescheiden, maar toch... - -Voor meer details kun je het beste even de file -"ZACHTPSG.PCT" inladen in Dynamic Publisher. Hierin staat -alles nog eens in een handig schema uitgelegd. - -Mocht je ondanks nog vragen hebben, bel dan eens met BBS -SUNRISE NOORD (dagelijks 22-7, tel: 05126-2123 of gewoon -spraak na 18:00 uur, vragen naar Haiko...) - -Veel luisterplezier, - -Haiko de Boer diff --git a/Sunrise Special/1/Track 0 op de turbo-r.md b/Sunrise Special/1/Track 0 op de turbo-r.md deleted file mode 100644 index 07873fb..0000000 --- a/Sunrise Special/1/Track 0 op de turbo-r.md +++ /dev/null @@ -1,78 +0,0 @@ -# T R A C K 0 O P D E T U R B O R - - -Het zal veel MSX turbo R bezitters al zijn opgevallen dat de -diskdrive veel meer geluid produceert bij het lezen of -schrijven van track 0 dan bij het lezen of schrijven van -andere tracks. Waarom is dat zo? - - -## B E L A N G R I J K E I N F O R M A T I E - -Track #0 bevat de logische sectoren #0 tot en met #17. -Sector #0 tot en met #8 op kant #0 en sector #9 tot en met -#17 op kant #1. Zoals u weet (of anders in de diskcursus op -deze Special kunt lezen) staat in deze sectoren zeer -belangrijke informatie, namelijk de bootsector, de FAT en de -directory. - -Deze informatie is zeer belangrijk voor het functioneren van -de diskette. Raakt deze informatie beschadigt, dan is de -informatie op de rest van de diskette slechts met grote -moeite bereikbaar. Vandaar dat het een absolute ramp is als -een van de sectoren #0 t/m #13 beschadigd raakt. - -## B U I T E N S T E T R A C K - -Een oplossing die bij alle computers gebruikt wordt, is het -feit dat track 0 de buitenste track is. Van binnen naar -buiten toe worden de tracks steeds groter, terwijl er toch -steeds dezelfde informatie op staat. U begrijpt dat er -minder storingen optreden indien de informatie verder uit -elkaar staat. Daarom is het beter om voor de zo belangrijke -track 0 de buitenste track te gebruiken. - - -## E X T R A V E I L I G - -Bij het ontwikkelen van de turbo R vond men dit blijkbaar -nog niet genoeg, want op de turbo R krijgt track 0 een -speciale behandeling, die nog veiliger is. - -Ik weet niet precies wat deze speciale behandeling doet, -maar vast staat dat het herrie maakt! Veel extra tijd kost -het echter niet, het verschil in snelheid tussen het inlezen -van track 0 en een willekeurige andere track is nihil. - - -## E I G E N L I J K S T I L - -De diskdrive van de turbo R is eigenlijk erg stil. Zelfs -diskettes die op mijn vorige computer (een Sony HB-F700P -MSX2) "aanliepen" werken nu geruisloos. Behalve bij track 0 -dan natuurlijk. - -Je kan het goed merken als je een diskette met een sector- -kopieerprogramma kopieert. Aan het begin wordt track 0 -gelezen, dat maakt herrie, en daarna hoor je bijna niets -meer. Alleen het "overstappen" van de kop van de diskdrive -naar een andere track is te horen door een klein tikje. -Verder is de diskdrive zeer stil! - -Maar bij het inlezen/wegschrijven van files produceert de -turbo R wel redelijk wat geluid. Dit komt omdat de meeste -files niet al te lang zijn, en dus de voornaamste tijd in -beslag wordt genomen door het lezen van de directory en de -FAT. En dat maakt nou precies die herrie... - - -## B E T R O U W B A A R - -Ik neem het geluid voor lief, want de diskdrive van de turbo -R is wel zeer betrouwbaar. Ik heb mijn turbo R al bijna een -jaar, maar heb nog nooit last gehad van kapotte sectoren in -de FAT of directory. Bij mijn vorige computer kwam dat wel -zo af en toe voor. Blijkbaar helpt die speciale behandeling -uitstekend! - -Stefan Boer diff --git a/Sunrise Special/2/Cursus dd-graph.md b/Sunrise Special/2/Cursus dd-graph.md deleted file mode 100644 index b68718e..0000000 --- a/Sunrise Special/2/Cursus dd-graph.md +++ /dev/null @@ -1,448 +0,0 @@ -# C U R U S D D - G R A P H - - -DD-Graph is een tekenprogramma dat is ontwikkeld door T&E -Soft, het werkt op een MSX2 en hoger op grafisch scherm 5. -Het programma is volgens mij niet (meer) in Nederland te -verkrijgen maar omdat het programma erg veel gebruikt wordt -en de handleiding in het Japans is heb ik deze cursus -geschreven. (N.B. Omdat het programma erg veel mogelijkheden -bevat en het onmogelijk is het in 16 kB helemaal uit te -leggen, is dit artikel in 2 delen, nl. DD-GRAPH -1- en -2- -terug te vinden in het submenu. - -We zullen maar beginnen bij het begin en dat is bij het -opstart-menu, hier kan worden gekozen tussen: AGE, het -SCREEN 5 tekenprogramma en SPEN, het sprite ontwerp- -programma. Wij beginnen met de bovenste keuze en dat is AGE -(de tweede keuze is SPEN en de derde is terug naar DOS.) - - -## A G E - - - -### S P E C I A L E T O E T S E N - -(Even van te voren, als ik het over de rechter en linker -muisknop heb, is dat hetzelfde als F1 en F2.) - -Als AGE is opgestart verschijnt er een pijltje in het beeld -dat kan worden bestuurd met de muis in poort 1 of met de -cursortoetsen. Als er voor de cursor toetsen wordt gekozen -zijn er twee extra toetsen nl. [SELECT] en [SHIFT]. Met -[SHIFT] gaat het pijltje iets sneller en met [SELECT] -beweegt het pijltje in blokken. De [SHIFT] functie werkt -overigens ook met de muis. - -De muis en de cursors kunnen ook tegelijker tijd worden -gebruikt. Als de muis niet in poort 1 zit en AGE is al -opgestart moet de muis in poort 1 gestopt worden en op de -[STOP] toets gedrukt worden, nu herkent AGE de muis wel! Als -men met de cursors werkt komen de functietoetsen F1 en F2 -overeen met respectievelijk de linker en rechter muisknop. - -De functietoets F5 zorgt voor een COLOR=NEW, d.w.z. dat het -palet weer op de standaard kleuren wordt gezet. Met de [ESC] -toets neemt men de kleur waar het pijltje tijdens het -indrukken van de [ESC] opstond. Als men de rechter muisknop -indrukt en ingedrukt houd en daarna de linker muisknop in -drukt en vervolgens de muisknoppen tegelijkertijd(!) los -laat geeft dit hetzelfde effect als de [ESC] toets. Met de -CTRL toets en de cursor toetsen kan men het beeld centreren. - -Het kleurenpalet kan worden verplaatst door op het witte -blokje boven het palet te gaan staan en dan op de linker -muisknop te drukken en vervolgens het palet op de gewenste -plaats te zetten en nogmaals op de linker muisknop te -drukken. Als men het palet helemaal wil laten verdwijnen -moet men met het pijltje op hetzelfde witte blokje gaan -staan en dan de linker muisknop indrukken (en ingedrukt -houden) en vervolgens de rechter muisknop ook indrukken en -tegelijkertijd(!) loslaten. - -Met de [GRAPH] toets kan men het submenu laten zien van de -laats gekozen functie. Met de cijfertoetsen 1 tot en met 3 -kan men pagina 1 tot en met 3 laten zien (waar dit voor is -leg ik de volgende keer wel uit!). Er kan NIET op deze -schermen gewerkt worden, althans U kunt niet een stip op een -pagina neerzetten waar U de cijfertoets van ingedrukt houdt, -de stip zal gewoon op de huidige pagina worden gezet!!! - -Ik denk dat ik nu wel alle speciale toetsen en -toetscombinaties heb genoemd, omdat het er veel zijn maak er -even een overzicht van (handig voor een screendump!). -cOVERZICHT. - -Toets of toetscombinatie: Uitwerking : -------------------------------------------------------------- -SELECT.................... Pijltje beweegt in blokken. -------------------------------------------------------------- -SHIFT .................... Het pijltje beweegt sneller. -------------------------------------------------------------- -STOP ..................... Muis in poort 1 aangesloten ? -------------------------------------------------------------- -F-1 ...................... Hetzelfde als de linker muisknop. -------------------------------------------------------------- -F-2 ...................... Hetzelfde als de rechter muisknop. -------------------------------------------------------------- -F-5 ...................... Geeft een color=new. -------------------------------------------------------------- -ESC of de R+L muisknop ... Kleur waar pijltje opstaat=actief. -------------------------------------------------------------- -CTRL + CURSORS ........... Centreren beeld. -------------------------------------------------------------- -Linker muisknop op blokje. Verplaatsen van kleuren palet. -------------------------------------------------------------- -Beide muisknoppen op blok. Verwijderen palet. -------------------------------------------------------------- -GRAPH .................... Show laatst gekozen functie+menu. -------------------------------------------------------------- -Cijfertoetsen 1 t/m 3 .... Laten zien van de pagina's 1,2,3. -------------------------------------------------------------- - -Dan zal ik nu de 16 functies gaan bespreken uit het -menu-balkje onderin het menu. (Zie ook het tweede deel van -deze tekst in het submenu genaamd: DD-GRAPH -2-.) - - -### D E F U N C T I E S - -De eerste functie: L I N E , (helemaal linksonder) als we -deze functie kiezen met de linker muisknop dan kunnen we -gewoon lijnen trekken die niet aan elkaar vast zitten. Als -we echter op het icoon op de rechter muisknop drukken komen -we in een submenu, hier kunnen we kiezen uit conected line -en radial line. De eerste keuze trekt lijnen die wel aan -elkaar vast zitten d.w.z. waar de ene lijn stopt begint de -andere. De tweede keuze trekt lijn vanuit een punt, een -zogenaamd waaier-effect. - -De tweede functie: D R A W , (rechts naast LINE) nadat we -met de linker muisknop op dit icoon hebben gedrukt kunnen we -vervolgens met de hand tekenen. Als we echter op de rechter -muisknop drukken komen we in het submenu en kunnen we kiezen -of we met een patroon willen tekenen of met gewone lijnen, -als het rondje ingekleurd is tekenen we wel met het gekozen -patroon en anders niet. - -De derde functie: B O X , (rechts naast DRAW) deze functie -spreekt voor zich. Hiermee kunnen we rechthoeken maken maar -ze worden NIET ingekleurd. - -Nu wordt het wat ingewikkelder, als we nl. op de rechter -muisknop drukken met het pijltje op het BOX icoon, komen we -in een submenu waar de stappen die de MUIS moet maken, -kunnen worden ingevuld. Dit werkt als volgt: we zien twee -pijltjes naar rechts en twee naar links, ook zien we twee -pijltjes naar links met een streep erachter. Met de pijltjes -naar links en naar rechts kunnen de stappen met 1 stap -verhoogd en met 1 stap velaagd worden. Met de pijltjes met -de streep erachter kunnen de stappen alsvolgt verhoogd -worden: 2, 4, 8, 16, 64, 128 enz. Ook kunnen de stappen weer -hersteld worden d.m.v. CLEAR. (N.B. stappen is erg -gemakkelijk als je b.v. een karakterset van 16x16 moet -tekenen, dan neem je gewoon de stappen 16 en 16.) - -De vierde functie: B O X F I L L , (rechts naast BOX). BOX -FILL werkt hetzelfde als BOX alleen het vierkant wordt WEL -ingekleurd. Ook is het submenu hetzelfde als bij BOX. - -De vijfde functie: C O P Y , (rechts naast BOX FILL). Met -COPY kan je gewoon delen van de pagina kopi�ren naar een -andere plaats. Er zijn daar 4 manieren voor: 1 XOR, 2 OR, 3 -TPSET en 4 SWAP, deze zijn te kiezen door het submenu op te -roepen op de bekende manier en daar aan te klikken wat men -wilt. Met XOR en OR worden de kleuren respectievelijk -ge'XOR'd en ge'OR'd. Met TPSET (TIMP) kan er worden -gekopieerd maar kleur 0 is doorzichtig, dus je beschadigt -het deel waarover je met kleur 0 kopieert niet! Dan is er -nog SWAP, met SWAP verplaats je de gekopieerde vlakken. Dus -alles dat onder het blok zat wat je kopieerde wordt -verplaatst naar de plek waar je vandaan kopieerde. - -De zesde functie: P A I N T , (rechts naast COPY). Deze -functie spreekt ook voor zich. Er kunnen gewoon stukken of -het hele scherm worden ingekleurd met de gekozen kleur. Er -zit geen optie achter het submenu, alleen wat info over AGE -en een klok. - -De zevende functie: C I R C L E , (rechts naast PAINT). -Nadat deze functie is gekozen kan je door een druk op de -linker muisknop het middenpunt van de cirkel bepalen. Nu de -grootte bepalen en nog een keer op de linker muisknop -drukken, klaar is kees. Er is ook bij deze functie geen -submenu. - -De achtste functie: T U R N , (rechts naast CIRCLE) is erg -handig om tekeningen of delen daarvan horizontaal of -verticaal te keren, het is dus mogelijk om b.v. de tekts -"HALLO" horizontaal te keren en dan staat er "OLLAH". De -richting van het keren wordt bepaald door het aanklikken van -1 van de pijltjes naast het palet. Geen submenu aanwezig. - -De negende functie: R O L L , (rechts naast TURN) werkt ook -met de pijltjes naast het palet. Met ROLL kun je een deel -van een tekening verschuiven, er verandert dus niets alleen -de plaats. Geen submenu aanwezig. - -De tiende functie: T R A N S , (rechts naast ROLL) en alweer -de pijltjes om te besturen. Met TRANS kunnen delen van een -tekening worden gedraaid, d.w.z. dat een horizontale -tekening verticaal kan worden gemaakt en andersom. Er is -echter een voorwaarde, het vlak dat je wilt "TRANS'EN" moet -vierkant zijn! Dus als je een langwerpig vlak hebt ben je -verplicht een heel ruim vlak te nemen. En helaas weer geen -submenu. - -De elfde en voor dit gedeelte laatste functie: 2 C O P Y . -Met deze functie kan je kleine vlakken vergroten en -andersom. Het werkt alsvolgt: je bepaald het gebied dat je -groter of kleiner wilt maken en daarna bepaal je de plaatsen -grootte van het plaatje, simpel toch?! Deze functie heeft -ook geen submenu. - -De twaalfde functie: Z O O M , (rechts naast 2COPY). Dit is -waarschijnlijk de meest gebruikte tekenfunctie maar is -daarentegen niet ingewikkeld! Na een druk op de rechter -muisknop kunnen we kiezen of we een loupe en/of een zoom -grid willen gebruiken. Zoom grid zijn ruitjes die over de -vergrote tekening worden gezet waarbij het tellen van hokjes -makkelijker wordt. Loupe is het blokje dat meestal in beeld -is wanneer er een functie is gekozen met de linker- -muisknop. In dit blokjes staat een vergroot beeld van de -plaats waar de pijl zich bevindt en de ruimte daar om heen, -voor de rest staan er de x positie en de y positie van het -pijltje, de kleur die zich momenteel onder het pijltje -bevindt en de nu actieve functie. - -Met de linker muisknop word er een deel van het beeld -vergroot weergegeven in een speciaal blok, in dit blok staan -bovenaan de kleuren 0 tot en met 15, in het midden staat het -vergrote blok en onder kan de keuze gemaakt worden of men -2x, 4x, 8x of 16x wil vergroten, ook kan het blokje met de -pijltjes verplaatst worden. Wanneer men op het vierkantje -gaat staan (wat om het normale scherm staat) en daarna op de -linker muisknop drukt, kan het vierkant verplaatst worden -over het hele scherm. Om hierna weer te vergroten drukt men -nogmaals op de linker-muisknop. - -De dertiende functie: C O L O R , (rechts naast ZOOM). Na -een druk op de linker muisknop, kunt u een bepaalde kleur in -het door u aangegeven vlak, vervangen door een andere kleur. -Teken een rechthoek, selecteer een kleur uit het palet en -wijs een kleur aan binnen de rechthoek. - -Als we op de rechter muisknop drukken komen we in het -submenu en hier kan het palet worden veranderd. Ik zal het -hele kleuren menu even van links naar rechts behandelen. -Helemaal links-boven staat COL=X dat is het huidige -kleurnummer (X loopt van 0 tot 15). Hieronder staat de kleur -van het huidige kleurnummer, dus dit blokje is blauw bij -kleurnummer 4, mits het standaard palet is ingesteld (F5!). -Dan volgt R, G en B onder elkaar, waar de waardes ingesteld -kunnen worden d.m.v. de blokjes. - -Een druk op de linker muisknop en het van links naar rechts -bewegen van de muis verandert de waarde. Hierna een rondje -met PAL(X) en een met INITIAL. Met PAL(X) kan worden -ingesteld of U palet 1 of 2 wilt veranderen. Wanneer U b.v. -kleurnummer 1 rood maakt in palet 1 en in palet 2 blauw, dan -zal, wanneer U op de rechter-muisknop drukt, de kleur 1 -overlopen van rood naar blauw en terug! - -Met INITIAL wordt palet 2 gelijk aan palet 1 gemaakt. Dan -volgen de kleuren 0 tot en met F (15 dus). In plaats van de -kleur aangeven in deze kleurenbalk kan U ook op COL=X gaan -staan en op de linker-muisknop drukken het kleurnummer zal -automatisch met 1 worden verhoogd. - -De veertiende functie: A N I M A T I O N , (rechts naast -COLOR). Hiermee kan een slide-show ofwel en animatie gemaakt -worden. Het werkt als volgt. U tekent een bal, of meerdere, -en drukt op de linker-muisknop wanneer het pijltje zich op -de Japanse tekens bevindt (de 14e functie dus, animation). - -Nu komt er een blokje in beeld met daarin START, END, DEL, -CLEAR en een SPEED regelaar. Nu zet U een vierkantje om het -balletje heen en zet deze willekeurig in het beeld, als U nu -maar 1 balletje hebt getekend dan klikt U nogmaals op de -linker-muisknop nadat U het vierkantje weer om het balletje -hebt gezet. Als U nu, onder de plaats waar U daarnet een -vierkantje hebt gezet, nog een vierkantje zet en daarna op -start drukt, zal U zien dat het balletje heen en weer -beweegt. (Zeer schokkerig, daarom is het aangeraden heel -veel vierkantjes neer te zetten!) - -Met SPEED kunt u nu de snelheid bepalen. Met END stopt de -animatie weer. Als U meerdere balletjes hebt getekend, b.v. -balletjes die ronddraaien, zet U een vierkantje om het -eerste balletje, plaats die in het beeld. Daarna zet U een -vierkantje om het tweede balletje, plaatst die op het eerste -en doet dit vervolgens bij alle balletjes. Na het STARTen -draait het balletje rond. Met DEL wist U een animatie en met -CLEAR de hele animatie. Animatie worden samen met de -tekening op DISK GESAVED dit kost overigens GEEN extra -ruimte! Wanneer u een animatie heeft die zeer snel moet -bewegen kunt u in het submenu kiezen voor HIGH SPEED -ANIMATION. - -De vijftiende functie: F I L E M O D E , (rechts naast -ANIMATION) is een zeer uitgebreide functie, ik zal proberen -het in deze tekst na te maken en daarna uit te leggen -waarvoor alles dient. Na een druk op de linker-muisknop -krijgt u: - -DISK SAVE | NAME[ . ] | DISK LOAD |ABCD|*.*|BAK -MEM SAVE | DELETE | MAKE | GE5| MEM LOAD | FILES |v^ - -Disk save - om tekeningen of delen daarvan op disk weg te - schrijven -Mem save - om tekeningen in het geheugen te bewaren (page1) -Name - om de naam in te voeren, via toetsenbord of via - monitor -Delete - om bestanden te wissen (hoeven geen AGE - bestanden te zijn) -Make - om een kleuren palet weg te schrijven -GE5 - kan worden veranderd in DAT en CMP, DAT voor - COPY files die later in SPEN ingeladen kunnen - worden en CMP voor hele pagina's die gecruncht - weg geschreven worden - GE5 files kunnen gewoon in BASIC ingeladen - worden, dit zijn files die met BSAVE weg - geschreven zijn (met palet, dat kan worden - teruggehaald door een COLOR=RESTORE na het - BLOAD,S commando) -Disk load - idemdito als disk save alleen dan laden -Mem load - idemdito als mem save alleen dan laden - (straks meer hierover!) -ABCD - huidige drive kiezen -*.* - alle files (dus ook niet-AGE files) -BAK - om BACK UP files te zien, wanneer een tekening - onder de zelfde naam wordt gesaved word er auto- - matisch een back up gemaakt, back ups zijn: - GE5BAK.AGE, CMPBAK.AGE en DATBAK.AGE -Pijltjes - om door de files heen te bladeren - -De ruimte onder MEM save is voor de errors en de -bevestigingsvragen. - -Na een druk op de rechter-muisknop krijgt U: - -O Load IMP O Mem Swap O END se sw -O Load timp O Sort dir Swap O Error se sw - -Load IMP - Nadat U een tekening ge'mem-saved' heeft, en een - andere tekening heeft geladen, kunt U nadat U - 'Load IMP' gekozen heeft, delen van de ge'mem- - saved' tekening over de ander laden. Een soort - SUPER-IMPOSED optie dus! Het palet van de laatst - geladen tekening wordt genomen. Voor diegene die - dat willen weten, de ge'mem-saved' tekening komt - terecht op pagina 1. -Load TIMP - Idemdito als Load IMP maar als het deel wat over - de tekening wordt geladen, stukken bevat met - kleur 0 wordt de andere tekening hierdoor zicht- - baar. Kleur 0 is dus doorzichtig. -Mem Swap - De tekening op pagina 1 (zie: Load Imp) wordt - naar de huidige pagina (page 2) gekopieerd en de - tekening die daar al stond word naar page 1 - verplaatst. -Sort dirSw- Ik zou het niet weten, iemand wel? (Nvdr. - Misschien wordt de directory wel gesorteerd als - deze switch wordt aangezet, niet de directory op - disk maar die in het geheugen.) -End se Sw - Het heeft iets met de errors te maken dacht ik. - Maar voor de rest? -Error seSw- Dit is om de herrie en kleurentroep uit te - schakelen, u weet het wel. Als je de diskette - b.v. niet in de drive hebt en dan een tekening - probeert te laden. - -De *.DAT files hebben nog wat extra aandacht nodig, want -wanneer U een DAT file gaat saven zal er altijd een vierkant -ter grootte van SPEN's editor verschijnen. Wilt u echter een -ander formaat saven dan is een klik op de rechter muisknop -voldoende. Hierna kunt u zelf uw blok bepalen. Let wel, Spen -laad alleen het deel dat past in! De *.DAT files zijn -overigens compatible met COPY files in BASIC. - -De laatste en zestiende functie: U N D O , (rechts naast de -FILE MODE). Deze functie is ook wel een install mode. Als u -nl. op de rechter muisknop drukt kunt u instellen of u: - -Auto Change Text Color Swap - wilt oftewel of de kleur van -het menu automatisch op de lichtste kleur gezet moet worden -en de achtergrond op de donkerste. - -Key repeat - Wanneer deze aanstaat zal na het vasthouden van -de linker muisknop, een auto-fire effect bereikt worden. - -MSX-DOS - Terug naar DOS. - -For color - Voorgrond kleur. - -Back color- Achtergrond kleur. - - -Zo, ik hoop dat het u allemaal duidelijk is geworden, hoe -AGE in elkaar zit. Nu geef ik nog wat tips over het gebruik -van AGE in het algemeen. - -- Bij het laden van plaatjes in BASIC kan een COLOR=RESTORE - ingegeven worden. Na dit commando zal het in AGE - ingestelde palet automatisch ingesteld worden. Zo zou het - er in BASIC uitzien: - - 10 SCREEN 5 - 20 BLOAD "PLAATJE.GE5",S - 30 COLOR = RESTORE - 40 IF INKEY$="" THEN 40 ELS END - -- Probeer nooit een niet *.DAT file inteladen met de DAT - file mode ingesteld, dit sloopt uw menu's door dat de - tekening dan over je menu's heen geladen wordt (dus in het - spritegeheugen!) Idem voor *.CMP files. - -- Wanneer u van plan bent om alleen AGE te gaan gebruiken, - kunt u het beste even een nieuwe batchfile aanmaken die - meteen AGE.COM start. Dit gaat als volgt: - - A>COPY CON AUTOEXEC.BAT [RETURN] - A>AGE [RETURN] - A>[CTRL] + [Z] [RETURN] - - Nu zal AGE direkt opstarten en niet steeds het intromenu! - - -## S P E N - - -Het kopje heeft eigenlijk geen zin omdat ik SPEN niet ga -bespreken. Wij hebben SPEN gebruikt voor Bozo's Big -Adventure maar behalve het 'SAVE'en en 'LOAD'en is ons niet -duidelijk hoe het programma werkt. Het is in ieder geval de -bedoeling met AGE sprites te ontwerpen, ze daarna in te -laden in SPEN, bij te werken en weg te saven. Met de -programma's DW2BAS.COM en DB2BAS.COM kunt u uw met SPEN -gemaakte DB of DW files, (deze files kunt u in een assembler -in laden en dan heeft u de complete sprite data!) omzetten -naar sprite-data's in BASIC. Met de SAMPLE*.* files kunt u -zien hoe het werkt. - - -## N A W O O R D - -Zo, dat zit erop, ik hoop dat ik met deze cursus het een en -ander over Dots Designer's Club (de originele titel!) -duidelijk heb gemaakt. Ik zou zeggen ga flink teken voor het -Magazine of de Special, misschien wel voor een eigen demo -voor de Picturedisk! Nou ja, dat zoekt u zelf ook maar uit! - -Bart Schouten - - -Nvdr. Als u wel meer over SPEN kunt vertellen, schrijf er -dan een tekst over en stuur die dan op een diskette naar de -Sunrise postbus. Uppen bij een van de twee Sunrise BBS'en is -ook goed. Bij voorbaat dank! \ No newline at end of file diff --git a/Sunrise Special/2/Geheugen schakelen.md b/Sunrise Special/2/Geheugen schakelen.md deleted file mode 100644 index 61be24b..0000000 --- a/Sunrise Special/2/Geheugen schakelen.md +++ /dev/null @@ -1,480 +0,0 @@ -# G E H E U G E N S C H A K E L E N - - -Een tijdje geleden vroeg iemand aan mij waarom de -replayroutine die bij FAC Soundtracker wordt geleverd niet -werkt als je hem gebruikt in een machinetaalprogramma dat -vanuit de bootsector opstart. - -Eerst wist ik het antwoord niet, maar toen ik de routine -eens bekeek zag ik al snel waar het aan lag: de FAC schakelt -het geheugen niet op de juiste manier! - -Waarom gaat het dan vanuit BASIC wel goed zult u denken. Om -dat uit te leggen, moet ik eerst uitleggen hoe het geheugen -geschakeld dient te worden. - - -## P R I M A I R E E N S U B S L O T E N - -Elke MSX computer heeft vier primaire sloten, die elk weer -kunnen worden gesplitst in vier subsloten. Zowel de primaire -als de subsloten worden genummerd van 0 tot 3. - -Een voorbeeld van een slotindeling is (FS-A1ST MSX turbo R): -``` - 0-0 0-2 3-0 3-1 3-2 3-3 - -0000 MAIN - RAM SUB - HIRO -3FFF ROM ROM - -4000 MAIN FM RAM KANJI DISK HIRO -7FFF ROM BASIC BASIC ROM - -8000 - - RAM KANJI - HIRO -BFFF BASIC - -C000 - - RAM - - - -FFFF -``` - -Slot 1 en 2 zijn de cartridge sloten, de indeling hiervan is -afhankelijk van wat men in het cartridgeslot stopt. Als er -een slotexpander in steekt, wordt het slot uitgebreid in -vier subsloten, bijvoorbeeld slot 1-0, 1-1, 1-2 en 1-3. - -Het MAIN ROM moet volgens de MSX standaard altijd in slot 0 -zitten, als slot 0 is geexpandeerd is dit dus slot 0-0. Het -MAIN ROM vanaf adres &H0000 bevat het BIOS (Basic Input -Output System), vanaf &H4000 staat de BASIC interpreter. - -Slot 0 is bij de turbo R geexpandeerd voor de FM BASIC, die -in slot 0-2 is geplaatst. In slot 3-0 zit het memory mapper -RAM, de I/O poorten &HFC t/m &HFF bepalen welke memory -mapper segmenten hier staan. De SUB ROM is de MSX2 BASIC, de -KANJI ROM is de MSX2+ en MSX turbo R BASIC. - -De diskROM zit op adres &H4000 in slot 3-2. Eigenlijk zijn -er bij de turbo R meerdere diskROMs, die met een -omschakeladres worden geselecteerd. Welke diskROM er is -geselecteerd is o.a. afhankelijk van de mode waarin de -computer werd opgestart (Disk BASIC 1.0 of Disk BASIC 2.01). - -In slot 3-3 bevindt zich tenslotte de ingebouwde -programmatuur, die ik hier voor het gemak Hiro noem. Dit is -het ingebouwde pakket, dat met een CALL HIRO of een reset -(met de keuzeschakelaar in de linker positie) is op te -roepen. - - -## S L O T I D - -De BIOS heeft een handige manier om een bepaald slot weer te -geven, dit is de zogenaamde slot ID byte. Deze byte is als -volgt opgebouwd: -``` -MSB 7 6 5 4 3 2 1 0 LSB - - E 0 0 0 --S-- --P-- -``` -E: slot geexpandeerd? (1=ja) -S: nummer van secundair slot -P: nummer van primair slot - -S wordt verwaarloosd als E=0. Enkele voorbeelden maken het -misschien duidelijker: - -Slot: ID-byte: - -2 &B00000010 &H02 -3-2 &B10001011 &H8B -3-3 &B10001111 &H8F -0 &B00000000 &H00 -0-0 &B10000000 &H80 - -Merk op dat er verschil is tussen slot 0 en 0-0!!! Dit is -natuurlijk alleen zo bij computers waarbij slot 0 is -geexpandeerd, maar als je een programma schrijft is het toch -meestal de bedoeling dat het op alle computers werkt denk -ik. - - -## B I O S R O U T I N E S - -De veiligste manier om met het geheugen te schakelen is -natuurlijk via het BIOS, zo hoort het ook via de standaard. -Het BIOS heeft de volgende routines voor slotschakeling e.d. -in huis: - -&H000C RDSLT - -Werking: Lees een byte uit een bepaald slot. Het slot - wordt geselecteerd, de byte wordt gelezen en de - oude slot schakeling wordt weer hersteld. De - interrupts worden uitgezet bij aanroep van deze - routine, en niet meer aangezet. -Input: A = slot ID byte - HL = adres -Output: A = data -Registers: AF, BC, DE - - -&H0014 WRSLT - -Werking: Schrijf een byte naar een bepaald slot. Het slot - wordt geselecteerd, de byte wordt geschreven en - de oude slot schakeling wordt weer hersteld. De - interrupts worden uitgezet bij aanroep van deze - routine, en niet meer aangezet. -Input: A = slot ID byte - HL = adres - E = data -Output: - -Registers: AF, BC, D - - -&H001C CALSLT - -Werking: Roept een routine in een bepaald slot aan (inter- - slot call). -Input: Bit 9-16 van IY = slot ID byte - IX = adres -Hangt verder af van de routine die wordt aangeroepen. Let op -dat hierbij de slot ID byte in de hoogste 8 bits van IY moet -staan (bij de R800 is dit IYL!). - - -&H0024 ENASLT - -Werking: Selecteer een slot zodat het kan worden gebruikt. - De interrupts worden bij het aanroepen van deze - routine uitgezet en niet meer aangezet. -Input: A = slot ID byte - H = bit 7 en 6 bepalen welke page -Output: - -Registers: allemaal -De waarde van de bits 6 en 7 van H bepalen welke page er -wordt geschakeld. Het komt er dus in feite op neer dat de -page wordt geschakeld naar de page waarin het adres voorkomt -dat in HL staat. - -Page 0 &H0000-&H3FFF H tussen &H00 en &H3F -Page 1 &H4000-&H7FFF H tussen &H40 en &H7F -Page 2 &H8000-&HBFFF H tussen &H80 en &HBF -Page 3 &HC000-&HFFFF H tussen &HC0 en &HFF - - -&H0030 CALLF - -Deze routine kan behalve met CALL &H0030 ook met RST &H30 -worden aangeroepen. Dit kost maar een byte in plaats van -drie, en is iets sneller. - -Werking: roept een routine in een bepaald slot aan (inter- - slot call) -Input en output zijn afhankelijk van de routine die wordt -aangeroepen. De waarde van AF wordt gewijzigd. De invoer van -adres en slot gaan als volgt: -``` - RST &H30 ; inter-slot call - DB SLOT ; slot ID byte van slot waarin - ; de routine staat - DW ADRES ; adres van aan te roepen routine -``` -Dit is dus een zeer snelle en korte methode om een routine -in een "ver" slot aan te roepen. Dit wordt veel gebruikt bij -hooks, daar is precies voldoende ruimte (5 bytes) om een RST -&H30 plus slot, adres en een RET neer te zetten. - -Voorbeeld: -``` - RST &H30 - DB &H83 - DW &H5A00 -``` -Hiermee wordt de routine op adres &H5A00 in slot 3-0 -aangeroepen. Dit was het overzicht van de BIOS routines voor -geheugen schakeling, nu gaan we verder met ons "probleem". - - -## R O M / R A M S C H A K E L E N - -Bij ML programma's die vanuit BASIC worden opgestart is het -vaak nodig om de MAIN ROM tijdelijk weg te schakelen en daar -RAM neer te zetten, bij programma's die vanuit MSX-DOS of de -bootsector opstarten is het vaak nodig om het RAM tijdelijk -weg te schakelen en daar RAM neer te zetten. Meestal moet de -oude situatie later weer worden hersteld. - -U kunt dit het beste doen met de routine ENASLT op adres -&H0024. Met H geeft u op welke page u wilt schakelen en in A -staat de slot ID byte. - -Waar haalt u nu de juiste slot ID byte vandaan? U zou -natuurlijk een routine kunnen schrijven die het RAM zoekt, -maar gelukkig heeft het besturingssysteem van de MSX -computer dit bij het opstarten al gedaan. Per page staat -er in het systeem RAM een slot ID byte die aangeeft in welk -slot het RAM voor die page staan. U kunt deze RAM ID bytes -vinden op de volgende adressen: - -Page 0 (&H0000-&H3FFF) Adres &HF341 -Page 1 (&H4000-&H7FFF) Adres &HF342 -Page 2 (&H8000-&HFFFF) Adres &HF343 -Page 3 (&HC000-&HFFFF) Adres &HF344 - -Normaal gesproken zijn deze slot ID bytes aan elkaar gelijk, -maar voor de zekerheid is het natuurlijk beter om altijd het -juiste adres te gebruiken. De computer zoekt overigens naar -de grootste mapper, die wordt bij het opstarten -geselecteerd. - -Met deze gegevens komen we tot de volgende standaard -routines. - -## R A M A A N - -Met deze routine selecteert u ROM op &H0000 (page 0): -``` - LD A,(&HF341) - LD H,&H00 - CALL &H24 -``` -Met deze routine selecteert u RAM op &H4000 (page 1): -``` - LD A,(&HF342) - LD H,&H40 - CALL &H24 -``` -Gebruik altijd deze methode, dan werkt het altijd. Bij het -wegschakelen van de BIOS op page 0 moet u er wel voor zorgen -dat de interrupts uit staan, of dat op adres &H0038 uw eigen -interrupt routine staat. Anders slaat de computer vrijwel -zeker vast zodra er een interrupt optreedt. - -Het wegschakelen van de MAIN ROM op page 1 (hier staat de -BASIC interpreter) zal in een ML programma meestal geen -problemen geven, er zullen zelden routines uit de BASIC -interpreter worden gebruikt. Vergeet niet het MAIN ROM weer -terug te schakelen voordat u weer naar BASIC terugkeert, -anders slaat de computer natuurlijk vast. - -Wilt u toch de routines in de BASIC interpreter gebruiken, -dan kunt u daarvoor de BIOS routine CALBAS gebruiken. Deze -routine staat op adres &H159, het adres van de routine die u -wilt aanroepen moet in IX staan. - - -## R O M A A N - -En nu zijn we dan tot de kern van de zaak doorgedrongen: wat -is de juiste manier om ROM te selecteren op page 0 en/of -page 1. - -Omdat de MAIN ROM zich in een MSX computer altijd in slot -0-0 of slot 0 bevindt, is er eigenlijk geen adres in het -systeem RAM dat u kunt uitlezen om de slot ID byte van het -MAIN ROM te vinden. - -Toch kunt u hem wel uit het MAIN ROM halen. Op adres &HFCC1 -staat namelijk een tabel van 4 bytes, die per primair slot -aangeeft of het slot is geexpandeerd of niet. Slot 0 staat -op &HFCC1, slot 1 op &HFCC2, enz. - -Deze tabel heet EXPTBL (EXPansion TaBLe). Er zijn slechts -twee waarden mogelijk: &H80 (wel geexpandeerd) en &H00 (niet -geexpandeerd). Het leuke is nu dat deze byte voor slot 0 -precies het slot van de MAIN ROM aangeeft! - -Is slot 0 namelijk geexpandeerd, dan staat er op adres -&HFCC1 een &H80, de slot ID byte van slot 0-0. Is slot 0 -niet geexpandeerd, dan staat er op adres &HFCC1 een &H00, de -slot ID byte voor slot 0! - -De juiste routines om ROM te selecteren zijn dus: - -ROM selecteren op &H0000 (page 0): -``` - LD A,(&HFCC1) - LD H,&H00 - CALL &H24 -``` -ROM selecteren op &H4000 (page 1): -``` - LD A,(&HFCC1) - LD H,&H40 - CALL &H24 -``` -Gebruik altijd deze methode, dan werkt het altijd! Helaas -zijn er veel programmeurs die het niet zo doen, hierover -gaat de volgende paragraaf. - - -## H O E H E T N I E T M O E T - -Een aantal (Nederlandse) programmeurs denken dat op adres -&HFCC0 de slot ID byte staat voor het MAIN ROM in page 0 en -op adres &HFCC1 de slot ID byte voor het MAIN ROM in page 1. -Dit is klinkklare onzin!!! Op adres &HFCC1 staat de slot ID -byte voor page 1 EN page 0!!! - -Helaas zijn er daarom veel programmeurs die als volgt ROM op -&H0000 selecteren: -``` - LD A,(&HFCC0) - LD H,&H00 - CALL &H24 -``` -Dit is dus echt helemaal fout!!! Doe dit dus nooit zo!!! Ik -snap wel hoe ze hierbij komen, het komt door CALSLT. Deze -BIOS routine wordt vaak onder MSX-DOS gebruikt om een BIOS -routine aan te roepen. Voor CALSLT moet de slot ID byte in -de HOOGSTE ACHT BITS van register IY staan. Dit kan als -volgt worden gedaan: -``` - LD IY,(&HFCC0) -``` -Op deze manier worden de laagste acht bits geladen met de -waarde op &HFCC0 (die waarde doet er verder niet toe), en de -hoogste acht bits (waar het om draait) met de waarde op -&HFCC1, precies zoals de bedoeling is. Hier komt misschien -de verwarring met &HFCC0 vandaan. - - -## B S A V E - -Dat het echt onzin is om &HFCC0 te gebruiken om de slot ID -byte van het MAIN ROM te achterhalen blijkt wel als we gaan -kijken wat er nu eigenlijk wel op &HFCC0 staat. Op adres -&HFCBF staat een 2 bytes waarde die SAVENT heet. Dit is een -beetje vreemde naam, want dit adres is het startadres bij -BSAVE en BLOAD: - -BSAVE"NAAM.BIN",beginadres,eindadres,startadres - -Dit adres staat dus op &HFCBF en &HFCC0, &HFCC0 bevat dus de -high byte van het BSAVE start adres!!! Misschien helpt een -voorbeeldje hier: - -BLOAD"NAAM.BIN",R - -is precies hetzelfde als - -BLOAD"NAAM.BIN" -DEFUSR=PEEK(&HFCBF)+256*PEEK(&HFCC0) -U=USR(0) - -U begrijpt dus wel dat elke programmeur die &HFCC0 gebruikt -om de slot ID byte te achterhalen niet helemaal goed bij -zijn hoofd is, want de waarde die daar staat is volkomen -onvoorspelbaar!!! - - -## H O E H E T O O K N I E T M O E T - -Een andere methode die ik vaak zie is de volgende, het maakt -hierbij niet uit of het om page 0 of page 1 gaat: -``` - XOR A - LD H,&H40 ; &H00 voor page 0 - CALL &H24 -``` -Zoals u weet is XOR A hetzelfde als LD A,0, voor de slot ID -byte wordt dus 0 genomen. Bij computers waar slot 0 niet -geexpandeerd is geeft dit natuurlijk geen problemen, maar -als slot 0 wel geexpandeerd kan dit problemen geven. - -Dit komt omdat de routine op &H24 naar bit 7 kijkt om te -kijken of het secundaire slot moet worden veranderd of niet. - -Stel u heeft een computer waarvan slot 0 is geexpandeerd -(bijvoorbeeld een turbo R), en u heeft slot 3-3 geselecteerd -op &H4000 (page 1). Nu doet u -``` - XOR A - LD H,&H40 - CALL &H24 -``` -om het ROM te selecteren op &H4000. Dit gaat nu mis! De -routine op &H24 kijkt immers naar bit 7, en die is gelijk -aan 0. Het gevolg is dat slot 0-3 wordt geselecteerd, dit -uiteraard met onbekende gevolgen (meestal een vastloper). - - -## H E T F S T P R O B L E E M - -U raadt het al: de replay routine van FAC Soundtracker doet -het niet altijd goed omdat hij het geheugen verkeerd -schakelt. Om precies te zijn schakelt FAC Soundtracker op de -volgende manier ROM op &H0000: -``` - LD A,(&HFCC0) - LD H,&H40 - CALL &H24 -``` -Zoals u weet bevat &HFCC0 de high-byte van het BSAVE -startadres, de waarde op dit adres is dus onvoorspelbaar. Er -wordt op deze manier dus naar een willekeurig slot -geschakeld, met onbekende gevolgen. - - -## W A A R O M W E R K T H E T M E E S T A L W E L ? - -De oplettende lezertjes vragen zich nu natuurlijk af waarom -FST.BIN onder BASIC wel altijd werkt. Dit wordt veroorzaakt -door toeval, oftewel ontzettende mazzel voor de FAC. - -Zoals u weet staat de MAIN ROM altijd in slot 0 of 0-0, -waarvan de slot ID bytes resp. &H00 en &H80 zijn. &H80 is -echter altijd goed, want als slot 0 niet geexpandeerd is -maakt het tenslotte niet uit of het subslot wordt veranderd -of niet. - -Blijkbaar staat er dus bij gebruik van FST.BIN vanuit BASIC -altijd &H80 op adres &HFCC0, anders zou de routine dus niet -op alle computers werken! Hoe komt die &H80 daar? - -Zoals u weet zijn zowel de drumkits als de muziekjes van FAC -Soundtracker binaire files van 16 kB. Dit zijn files van het -volgende type: - -BSAVE"FILENAAM.EXT",&H8000,&HBFFF,&H8000 - -Het startadres is dus &H8000, de high byte daarvan &H80. -Door het BLOADen van Soundtracker muziekjes of drumkits -wordt dus automatisch de waarde &H80 op adres &HFCC0 gezet -(en de waarde &H00 op &HFCBF, maar dat doet er hier niet -toe). En dat is nu precies de waarde die altijd werkt als -slot ID byte voor het MAIN ROM!!! Kortom, de FAC heeft -ontzettende mazzel gehad. - - -## D E M O R A A L - -Ik hoop dat alle Nederlandse programmeurs hier wat van -hebben geleerd, en voortaan de enige echte standaard -routines gebruiken om het geheugen te schakelen. Ik zal ze -hier voor de zekerheid nog maar een keer geven: -``` -RAM000: LD A,(&HF341) - LD H,&H00 - CALL &H24 - -RAM400: LD A,(&HF342) - LD H,&H40 - CALL &H24 - -ROM000: LD A,(&HFCC1) - LD H,&H00 - CALL &H24 - -ROM400: LD A,(&HFCC1) - LD H,&H40 - CALL &H24 -``` -De FAC is echt niet de enige die dit fout doet, er zijn -helaas veel meer Nederlandse MSX programmeurs die dit -verkeerd doen. Ik hoop dat dit artikel daar verandering in -gaat brengen... - -Stefan Boer diff --git a/Sunrise Special/2/Interrupt service routines.md b/Sunrise Special/2/Interrupt service routines.md deleted file mode 100644 index c9c4eb3..0000000 --- a/Sunrise Special/2/Interrupt service routines.md +++ /dev/null @@ -1,801 +0,0 @@ -# I N T E R R U P T S E R V I C E R O U T I N E S - - -Soms zit het mee en soms zit het tegen. Deze eerste regels -zijn als laatste aan het artikel toegevoegd omdat ik tot de -ontdekking ben gekomen dat een dergelijk artikel al op MCM -nummer 51 heeft gestaan. Ik ben zelf geen lid van MCM en zie -het blad vrij weinig. Ik heb de informatie nota bene van -Sunrise Magazine #1 af moeten halen waar een beschrijving -van MCM 51 op staat. Het is nooit de bedoeling van Sunrise -geweest om oud nieuws te gaan vertellen, maar ik wist gewoon -niet dat MCM al iets dergelijks gedaan heeft. Affijn, ik -weet niet precies wat er allemaal in dat artikel staat, maar -ik hoop dat ik wat informatie toe kan voegen zodat dit niet -een nutteloos artikel is. - -(Nvdr. Maak je maar niet ongerust, Alex. Jouw artikel is -veel beter en uitgebreider dan dat in MCM.) - - -## H E T M A K E N V A N E E N I S R - - -ISR is een algemeen gebruikte afkorting voor Interrupt -Service Routine, oftewel een routine die wordt aangeroepen -als er een interrupt optreedt. Interrupts bestaan al lang -als we het over de computerhistorie hebben, want ze zijn al -terug te vinden in de eerste commercieel verkochte -computers. Dat is ook niet zo gek als je bedenkt dat -interrupts heel handig kunnen zijn. De populariteit van -interrupts is bijna grenzeloos en er is tegenwoordig geen -processor meer in de handel die geen interrupt faciliteiten -biedt. Natuurlijk zijn er altijd situaties waarbij -interrupts alleen maar aan de complexiteit bijdragen, maar -omdat wij allen maar een simpele MSX bezitten komt die -situatie bij ons nauwelijks voor. - - -## I N T E R R U P T S V S P O L L I N G - -Polling is de tegenhanger van interrupts. Bij polling wordt -er geen interrupt gegenereerd, maar zal de CPU zelf -periodiek naar een randapparaat kijken of deze iets aan te -bieden heeft (om maar iets te noemen). Nu zal je misschien -denken dat polling de computer erg traag maakt, maar dat is -helemaal niet waar. Polling wordt nl. o.a. gebruikt bij -dingen waarvan je in zekere mate kunt voorspellen dat de CPU -er aandacht aan moet besteden zoals bij een screensplit. - -We kunnen dus rustig stellen dat polling zo gek nog niet is -en dat wordt nog een bevestigd door het feit dat de -reaktietijd van polling wel 10x zo hoog kan zijn als de -reaktietijd van een interrupt. Dit komt omdat de ISR eerst -de oude waarde van alle registers moet bewaren om daarna de -bron van de interrupt te achterhalen. Pas na deze testen kan -naar de routine gesprongen worden die de feitelijke aktie -moet uitvoeren. - -Met polling heb je dit alles niet, omdat de registers niet -bewaard hoeven te worden en je meteen na de test weet waar -de interrupt vandaan komt. Vooral bij tijdkritische signalen -is polling dus beter dan interrupts omdat je veel sneller -kunt reageren op een signaal. Natuurlijk blijft het bij -polling wel belangerijk dat je ongeveer weet wanneer er -getest moet worden omdat de reaktietijd ook heel laag kan -zijn indien je niet konstant aan het pollen bent maar ook -andere dingen doet. - -Het laatste voordeel van polling boven interrupts is het -feit dat je precies weet waar het lopende programma -onderbroken wordt als de polling positief blijkt. Met -interrupts moet je altijd nog oppassen bij bv. het -beschrijven van de VDP omdat daar geen interrupt tussendoor -mag komen. Met polling heb je dit probleem niet omdat je -immers weet waar het optreed. - - -## W A N N E E R I N T E R R U P T S ? ? - -ALs we het even over een algemene moderne computer hebben -kunnen we stellen dat interrupts voor twee hoofdsituaties -gebruikt worden en wel: -- bij het verwerken van binnenkomende data 'bursts'. -- bij het snel moeten kunnen reageren op een binnenkomend - tijdkritisch signaal. - -Een burst is een situatie waarin in korte tijd een grote -hoeveelheid data binnen kan komen. Een disk-controller -levert bv. complete clusters aan de CPU die dat dan maar -snel mag verwerken omdat het volgende blok er weer aan kan -komen (bij MSX zit dit echter niet op een interrupt, dat is -ook de reden waarom je geen muziek af kunt spelen tijdens -het laden). - -Het is maar moeilijk te voorspellen wanneer de data binnen -komt en daarom zijn interrupts eigenlijk verplicht bij deze -situatie omdat je anders in een polling lus moet gaan zitten -om toch snel te kunnen reageren en niet de kans te lopen een -complete cluster aan data mis te lopen. Op MSX moet het dus -met zo'n lus en men is daarin zelfs zo ver gaan om de -interrupts tijdens het lezen van disk stil te leggen omdat -de CPU anders wel eens tijd tekort kan komen. Polling is -hier dus niet de beste oplossing omdat die methode feitelijk -90% van de tijd test op iets dat er (nog) niet is. - -Bij een screensplit is dat echter een heel ander verhaal. -Daar is elke microseconde winst een grote vooruitgang omdat -je de beeldopbouw nu eenmaal niet even stil kunt leggen. -Screensplits zijn ook heel voorspelbaar omdat ze immers op -een vast tijdsinterval optreden en daarom is polling hier -een betere oplossing (ook vanwege de reaktiesnelheid). - -Kijk maar eens naar de bovenste screensplit van uw geliefde -magazine. U zult hier twee zwarte lijnen zien die o.a. het -gevolg zijn van de relatief trage reaktie van de interrupt. -Ik zal in de toekomst eens proberen om die screensplit te -vervangen door polling om op die manier ��n van de twee -lijnen weg te halen (je zult het dus vanzelf wel merken). - -Ik heb eigenlijk niet een uitgesproken mening over de manier -om een screensplit te detecteren omdat het praktisch blijkt -dat het niet zo gek veel uit maakt of je nu polling of -interrupts gebruikt om een screensplit mee af te handelen. -De regel dat je interrupts kunt gebruiken om tijdkritische -signalen op te vangen werkt met polling net zo goed. Je moet -er bij polling echter wel even op letten waar je de tests -uitvoert en dat is bij interrupts niet zo. Daar hoef je er -alleen maar voor te zorgen dat de interrupts zoveel mogelijk -aan staan. - - -## I S R M O G E L I J K H E D E N O P M S X - -Laten we maar eens wat methoden en programmaatjes bekijken -die interrupts afhandelen en polling uitvoeren. Om te -beginnen zullen we de interrupts behandelen. - -Om een interrupt goed te kunnen begrijpen zullen we toch met -de hardware moeten beginnen omdat de in overvloed aanwezige -zwarte klodders immers interrupts genereren. Daarom volgt nu -een standaard protocol waar ALLE interrupts mee werken: - -- Het randapparaat (een chip) genereert een interrupt en zet - deze op de INT lijn. - -- Op een gegeven moment honoreert de CPU deze interrupt en - gaat afhankelijk van de processor en de instelling van - deze processor naar een ISR. - -- Hier worden meestal eerst enkele registers op de stack - gezet. Op sommige processoren gebeurt dit zelfs - hardwarematig (zoals de IRQ lijn op een MC6809). Nu wordt - meestal eerst de bron van de interrupt gewist, omdat de - INT lijn van dat apparaat nog steeds aktief is. Wordt dit - niet gedaan dan zal na afronding van de ISR meteen weer - een interrupt optreden die naar dezelfde ISR springt. Dit - weghalen van de oorzaak van een interrupt wordt nog wel - eens vergeten waardoor het net lijkt of je programma vast - loopt terwijl het feitelijk gewoon eeuwig in de ISR blijft - hangen. - -- Nu wordt de feitelijke interrupt aktie uitgevoerd en nadat - alle registers weer van de stack gehaald zijn zal het - programma dat liep voor de interrupt hervat worden. - -Dan volgt nu een lijst van dingen die gebeuren als op een -MSX een interrupt optreed op de INT-lijn. - -- De CPU accepteert altijd de interrupt maar hoeft hem miet - noodzakelijk onmiddelijk te honoreren (dit is het geval - als een DI instruktie gedaan is). Als de CPU de interrupt - uiteindelijk toch honoreerd zal naar adres 38H gesprongen - worden. Hier staat normaal gesproken een ROM met op adres - 38H een sprong naar de eigenlijke ISR - -- In de ISR aangekomen worden eerst alle registers op de - stack gezet (ook schaduwregisters). Nu wordt naar adres - FD9AH gesprongen. Zodra dit gedaan is wordt gekeken of de - interrupt van het 50/60Hz signaal van de VDP afkomstig is - en wordt naar FD9FH gesprongen indien dit zo is. - -- Nu wordt het toetsenbord afgetast en ook worden alle - vuurknoppen gelezen en bewaard. Bij een MSX2+ en de turbo - R wordt ook naar de PAUZE toets gekeken wordt en wel - nadat naar FD9AH gesprongen is. - - -Wat nu volgt is een listing van het voor ons belangrijke -deel van de MSX2 ISR. Nogmaals, de ISR's van de 2+ en de -turbo R zijn een beetje anders (dat verklaart voor een deel -waarom screensplits op de turbo R vaak fout gaan indien deze -voor MSX2 geschreven zijn). -``` -&H0038 C33C0C JP &H0C3C - -&H0C3C E5 PUSH HL ; Push registers -&H0C3D D5 PUSH DE -&H0C3E C5 PUSH BC -&H0C3F F5 PUSH AF -&H0C40 D9 EXX -&H0C41 08 EX AF,AF -&H0C42 E5 PUSH HL ; Push schaduwregisters -&H0C43 D5 PUSH DE -&H0C44 C5 PUSH BC -&H0C45 F5 PUSH AF -&H0C46 FDE5 PUSH IY ; Push indirektie reg. -&H0C48 DDE5 PUSH IX -&H0C4A CD9AFD CALL &HFD9A ; Algemene INT.hook -&H0C4D CD7914 CALL &H1479 ; 50/60Hz VDP int. ? -&H0C50 F2020D JP P,&H0D02 ; Nee -&H0C53 CD9FFD CALL &HFD9F ; 50/60Hz timing hook -&H0C56 FB EI ; Zie: Opm. 1 -&H0C57 32E7F3 LD (&HF3E7),A ; Bewaar S#0 voor BASIC -&H0C5A E620 AND &H20 ; Spritebotsing ? -&H0C5C 216DFC LD HL,&HFC6D ; Zie: Opm. 2 -&H0C5F C4F10E CALL NZ,&H0EF1 -&H0C62 2AA2FC LD HL,(&HFCA2); Voor: ON INTERVAL= -&H0C65 2B DEC HL -&H0C66 7C LD A,H -&H0C67 B5 OR L -&H0C68 2009 JR NZ,&H0C73 -&H0C6A 217FFC LD HL,&HFC7F -&H0C6D CDF10E CALL &H0EF1 ; Zie: Opm. 2 -&H0C70 2AA0FC LD HL,(&HFCA0) -&H0C73 22A2FC LD (&HFCA2),HL; Herstart ON INTERVAL= -&H0C76 2A9EFC LD HL,(&HFC9E) -&H0C79 23 INC HL -&H0C7A 229EFC LD (&HFC9E),HL; Softwareklok verhogen -&H0C7D 3A3FFB LD A,(&HFB3F) ; Doe PSG PLAY statement -&H0C80 4F LD C,A -&H0C81 AF XOR A -&H0C82 CB19 RR C -&H0C84 F5 PUSH AF -&H0C85 C5 PUSH BC -&H0C86 DC3111 CALL C,&H1131 -&H0C89 C1 POP BC -&H0C8A F1 POP AF -&H0C8B 3C INC A -&H0C8C FE03 CP &H03 -&H0C8E 38F2 JR C,&H0C82 ; Doe volgende PSG stem -&H0C90 21F6F3 LD HL,&HF3F6 ; Zie: Opm. 3 -&H0C93 35 DEC (HL) -&H0C94 206C JR NZ,&H0D02 ; Einde ISR -&H0C96 3601 LD (HL),&H01 -&H0C98 AF XOR A -&H0C99 CD0212 CALL &H1202 ; Lees ALLE vuurknoppen -&H0C9C E630 AND &H30 -&H0C9E F5 PUSH AF -&H0C9F 3E01 LD A,&H01 -&H0CA1 CD0212 CALL &H1202 ; idem. -&H0CA4 E630 AND &H30 -&H0CA6 07 RLCA -&H0CA7 07 RLCA -&H0CA8 C1 POP BC -&H0CA9 B0 OR B -&H0CAA F5 PUSH AF -&H0CAB CD1C12 CALL &H121C ; idem. -&H0CAE E601 AND &H01 -&H0CB0 C1 POP BC -&H0CB1 B0 OR B -&H0CB2 4F LD C,A -&H0CB3 21E8F3 LD HL,&HF3E8 ; Bewaaradres vuurknoppen -&H0CB6 AE XOR (HL) -&H0CB7 A6 AND (HL) -&H0CB8 71 LD (HL),C -&H0CB9 4F LD C,A -&H0CBA 0F RRCA -&H0CBB 2170FC LD HL,&HFC70 ; Spatiebalk bewaaradres -&H0CBE DCF10E CALL C,&H0EF1 -&H0CC1 CB11 RL C -&H0CC3 217CFC LD HL,&HFC7C ; Joy 2 knop 2 -&H0CC6 DCF10E CALL C,&H0EF1 -&H0CC9 CB11 RL C -&H0CCB 2176FC LD HL,&HFC76 ; Joy 2 knop 1 -&H0CCE DCF10E CALL C,&H0EF1 -&H0CD1 CB11 RL C -&H0CD3 2179FC LD HL,&HFC79 ; Joy 1 knop 2 -&H0CD6 DCF10E CALL C,&H0EF1 -&H0CD9 CB11 RL C -&H0CDB 2173FC LD HL,&HFC73 ; Joy 1 knop 1 -&H0CDE DCF10E CALL C,&H0EF1 -&H0CE1 AF XOR A -&H0CE2 32D9FB LD (&HFBD9),A ; Zie: Opm. 4 -&H0CE5 CD120D CALL &H0D12 -&H0CE8 2018 JR NZ,&H0D02 -&H0CEA 21F7F3 LD HL,&HF3F7 ; Zie: Opm. 5 -&H0CED 35 DEC (HL) -&H0CEE 2012 JR NZ,&H0D02 -&H0CF0 3602 LD (HL),&H02 -&H0CF2 21DAFB LD HL,&HFBDA -&H0CF5 11DBFB LD DE,&HFBDB -&H0CF8 010A00 LD BC,&H0A -&H0CFB 36FF LD (HL),&HFF ; Oude toestand toetsbrd. -&H0CFD EDB0 LDIR ; matrix wissen -&H0CFF CD4E0D CALL &H0D4E -&H0D02 DDE1 POP IX -&H0D04 FDE1 POP IY -&H0D06 F1 POP AF -&H0D07 C1 POP BC -&H0D08 D1 POP DE -&H0D09 E1 POP HL -&H0D0A 08 EX AF,AF -&H0D0B D9 EXX -&H0D0C F1 POP AF -&H0D0D C1 POP BC -&H0D0E D1 POP DE -&H0D0F E1 POP HL -&H0D10 FB EI -&H0D11 C9 RET - -&H0EF1 7E LD A,(HL) -&H0EF2 E601 AND &H01 -&H0EF4 C8 RET Z - . (Voor ons onbelangrijke code) - . - . - -&H1479 DBBA IN A,(&HBA) ; Lichtpen poort -&H147B E610 AND &H10 -&H147D 200D JR NZ,&H148C -&H147F 21FFFA LD HL,&HFAFF ; (Lightpen int request) -&H1482 CBFE SET 7,(HL) -&H1484 3E20 LD A,&H20 -&H1486 D3BB OUT (&HBB),A ; Ook lichtpen -&H1488 F608 OR &H08 -&H148A D3BB OUT (&HBB),A -&H148C DB99 IN A,(&H99) ; Lees statreg. 0 van VDP -&H148E A7 AND A ; Zie ook: Opm 5 -&H148F C9 RET -``` - -Opm. 1 -Nadat naar &HFD9F is gesprongen worden de interrupts weer -aangezet en dit doet men om snel op bv. een nog komende -screensplit te kunnen reageren. Deze screensplit wordt dan -dus afgehandeld terwijl de vorige int ook nog 'bezig' is. -Meestal zal dit goed gaan, maar als het fout gaat dan is het -een lastig te vinden fout omdat hij alles behalve voor de -hand ligt. Ik raad het vroegtijdig aanzetten van interrupts -af omdat het een extra onzekere faktor aan programma's -toevoegt. - -Indien blijkt dat de afhandeling van een interrupt te lang -duurt moet je in de ISR gewoon een byte 'hoog' zetten zodat -een aparte routine buiten de ISR zich hier op kan timen. Dit -heeft als gevolg dat je een hele snelle ISR krijgt terwijl -de responstijd wel iets lager wordt. De methode is dus -alleen bruikbaar bij routines die geen extreem snelle -responstijd nodig hebben zoals een muziek replay routine -(alhoewel je wel een volkomen leek moet zijn om een -replayroutine zo traag te maken dat hij niet op de interrupt -kan!!). - -Indien er een interrupt optreedt als de INT lijn nog steeds -aktief is (oftewel als de bron van de interrupt nog niet -weggehaald is) zal een andere eventueel optredene interrupt -van dezelfde bron (bv. de VDP) verloren gaan en nooit -afgehandeld worden. Dit is gewoon een hardwareprobleem en -kan verder niet opgelost worden. Het is dus handig om liefst -snel na het optreden van een interrupt de bron te 'wissen'. - -Iets wat veel mensen vergeten te doen is het bewaren van -register A tijdens de &HFD9F hook omdat die na deze CALL nog -bewaard wordt en de verdere afhandeling van een sprite -botsing hangt ook nog van deze waarde af. Het is echter wel -handig dat je A zelf moet bewaren omdat je de ISR zo een -beetje kunt manipuleren. Als laatste instruktie voor de RET -van &HFD9F zou je A op een voor jou gunstige waarde kunnen -zetten. Ikzelf heb echter nog nooit een zinvolle invulling -aan deze mogelijkheid kunnen geven. - - -Opm. 2 -In het systeem RAM van de BIOS staat een tabel, TRPTBL -geheten met daarin een aantal plaatsen om alle mogelijke -BASIC interrupts in kwijt te kunnen. Zo heeft elke -funktietoets hier een byte in en ook de stop toets, een byte -voor de spritebotsing, de spatiebalk en alle joystick -vuurknoppen. Als laatste staat hier een byte voor de -INTERVAL instruktie in. Buiten BASIC wordt hier echter -weinig gebruik van gemaakt, dus ik zal er verder geen -woorden aan vuil maken. - - -Opm. 3 -Deze instrukiereeks zorgt er voor dat om de twee VDP -interrupts zowel het toetsenbord als alle vuurknoppen -gescanned worden. De preciese werking van dit blok code is -niet belangerijk omdat deze code toch alleen maar data -aanmaakt voor de eenvoudig te gebruiken BIOS calls. - - -Opm. 4 -Om te voorkomen dat bij het printen van een ASCII dubbelcode -twee toetsenbordklikken gegenereerd worden is dit byte -ingevoerd. Ik vind dit een behoorlijk klungelig iets om in -een ISR te zetten, maar de Microsoft jongens wisten zeker -niets beters. - - -Opm. 5 -Dit is het mechanisme dat de toetsenbord toetsherhaling -bijhoudt. Als dit er niet in had gezeten dan hadden we nu -allemaal heel houterig op ons toestenbord moeten drukken -omdat je anders om de haverklap een dubbel 'e' aan zou slaan -om maar een voorbeeld te geven. Deze routine zorgt er voor -dat nadat ��n toets ingedrukt is het even duurt voordat de -herhaling begint. - - -## D I T K A N B E T E R O F N I E T S O M S - -Natuurlijk kunnen wij zo'n ISR veel beter schrijven dan die -oenen van Microsoft (geen wonder dat IBM met Apple samen is -gaan werken). De MSX ISR is allemaal wel heel leuk en -aardig, maar de routine bevat eigenlijk geen nuttige dingen -voor de gemiddelde machinetaal programmeur. De ISR is dan -feitelijk ook geschreven om BASIC wat meer mogelijkheden te -geven maar daar hebben wij weinig aan. De routine is niet -alleen onhandig voor ons, maar ook nog eens onnodig traag -(we gebruiken immers bijna niets van de informatie die de -ISR aanmaakt). Wat we dus nodig hebben is een manier om al -die zinloze ellende over te slaan en daar bestaat een -buitengewoon leuk geintje voor. - - -## D E I N T E R R U P T B Y P A S S - -Wat we gaan doen is ervoor zorgen dat de interrupt alleen -nog maar naar &HFD9A springt en de rest overslaat. Ik zal nu -even een voorbeeld geven hoe je zoiets aanpakt. -``` -V_BLNK: EQU &HFD9F - - ORG &HFD9A ; Ints staan uit !!!!!!!! - JP VDPISR - -; De ISR waar alle interrupts naar toe springen -VDPISR: IN A,(&H99) ; Lees S#0 en wis bron van int. - PUSH AF - CALL LNEISR ; = Wat eerst op &HFD9A stond - POP AF - RLCA ; Bit 7 in Cy - CALL C,V_BLNK ; &HFD9F hook aanroepen (=VDP int.) - POP AF ; Haal terugkeeradres van stack - POP IX - POP IY - POP AF - POP BC - POP DE - POP HL - EX AF,AF - EXX - POP AF - POP BC - POP DE - POP HL - EI - RET -``` -V_BLNK is een afkorting voor Vertical Blank en het is een -standaars benaming (op zo'n beetje ALLE computers behalve -MSX) voor de standaard 50 of 60Hz interrupt die de computer -genereert. - -Het leuke van deze routine is dat je feitelijk een beetje -met de stack gaat knoeien om de routine naar je eigen hand -te zetten. De POP AF die na de &HFD9F call staat haalt het -terugkeeradres van de stack dat er door de CALL &HFD9A van -de ISR op is gezet. Nu hoef je alleen nog maar de gePUSHte -registers weer van de stack af te halen om de stack weer zo -te maken als hij was voordat de interrupt optrad. De RET -waar de routine mee eindigt springt terug naar de routine -waar de computer mee bezig was voordat de interrupt optrad. - -Op deze manier sla je dus zo'n beetje alles van de standaard -ISR over en heb de feitelijk het hele besturingssysteem plat -gelegt. Het voordeel van deze methode is dat je nog steeds -de beschikking hebt over de BIOS en dat je (op een aantal -na) nog steeds van deze funkties gebruik kunt maken. Dingen -als de toetsenbordaftasting werken echter niet meer, dus als -je nu iets van toetsenbord wilt lezen dan zal je de matrix -moeten scannen met bv. BIOS call &H0141. - -Een ander voordeel van deze methode is het feit dat de PAUZE -toets niet meer uitgelezen wordt op een MSX2+ en een turbo R -computer. De PAUZE toets wordt dus gewoon uitgeschakeld en -dat is bijzonder prettig. - -(Nvdr. Alleen softwarematige pauzetoetsen, zoals bij de -turbo R, kunnen op deze manier worden uitgeschakeld. De Sony -MSX2+ computers hebben een hardwarematige PAUZE toets, en -die is op deze manier natuurlijk niet te omzeilen.) - -Deze routine simuleert feitelijk de standaard ISR omdat bij -elke interrupt naar LNEISR gesprongen zal en ook naar V_BLNK -indien het een VDP int. is. Dit is echter niet zo'n handig -systeem. Je kunt beter naar LENISR springen als het geen VDP -int. is en anders naar V_BLNK Je springt dan dus niet meer -naar beide als het een VDP int. is. Op deze manier is de -reaktiesnelheid op een VDP int. hoger als bij de gegeven -routine staat. - -Het ziet er dan ongeveer zo uit: -``` -DOINT: IN A,(&H99) - RLCA - PUSH AF - CALL C,V_BLNK ; VDP int eerst voor snelle reaktie - POP AF - CALL NC,LNEISR ; Alleen bij screensplit - POP AF - POP IX - . - . - etc. -``` -Overigens kan alleen de VDP interrupts doorgeven aan de -processor via de CPU interrupt pin. Geen enkel ander IC kan -een interrupt aan de CPU doorgeven (als dit niet waar is, -dan hoor ik dat nog wel) ook al heeft dat IC daar wel -capaciteiten voor (zoals de klokchip dat een alarm kent). - -Voordat ik verder ga met het schrijven van een kompleet -eigen ISR wil ik toch eerst even wat kwijt over de andere -interrupts en de interrupt faciliteiten van de Z80, maar dat -kan je allemaal op de volgende submenu-optie lezen. - -## M O D E S - -De Z80 kent 3 verschillende 'modes' van interruptafhandeling -Deze modes kunnen met een simpele instruktie aangezet -worden. Ze heten: - -IM 0 <= Op MSX niet gedefinieerd!! -IM 1 <= Op MSX gebruikt -IM 2 <= Op MSX niet gedefinieerd!! - -Mode 0 kan alleen worden gebruikt als de interruptbron via -een I/O-module met de Z80 verbonden is. Bij een int. in mode -0 moet de I/O-module nl. ��n van de 8 ReSTart instrukties op -de databus zetten waarna de CPU automatisch naar dat adres -zal springen. Je kunt op deze manier dus 8 snelle ISR's -maken zodat de CPU niet hoeft te testen waar de int. vandaan -komt omdat de bron dat zelf al verteld heeft. Het nadeel van -deze methode is dat er een extra stuk hardware nodig is om -alles te kunnen realiseren (de I/O-module). Ik meen te weten -dat het op MSX wel werkt, maar het is absoluut niet -gedefinieerd en het kan dus in principe op elk nieuw type -MSX fout gaan. Dit geldt ook voor IM 2! - -Mode 1 is de mode die op MSX gebruikt wordt en daar hebben -we het straks weer over. - -Mode 2 heeft hetzelfde probleem als mode 0 want ook hier -moet er een I/O-module aanwezig zijn. Deze module levert -echter een 'vektor' aan de CPU en geen adres. Deze vektor is -8 bits groot en is het LOWBYTE van een 16 bits adres waarvan -het HIGHBYTE in het I-register staat. Dit register en de -vektor vormen samen een adrespointer. Op dit adres moet dan -feitelijk het adres staan waar de computer heen moet -springen. Op deze manier is het mogelijk om 128 -verschillende ISR's te maken (bit 0 van het gegenereerde -getal is nl. 0) zodat zonder ook maar 1 test te doen over -waar de interrupt vandaan komt naar de juiste routine wordt -gesprongen. Ook hier geldt dat met de huidige IC's extra -hardware nodig zal zijn om het te realiseren, maar het is in -het verleden toch een veel gebruikte methode geweest. Als -iemand het dus over vektor interrupts heeft, dan weet je nu -waar hij het over heeft. - - -## E V E N E E N A A N T A L F E I T E N - -Laten we nu eerst maar eens opsommen wat we precies weten. - -Een interrupt wordt altijd geaccepteerd, maar niet nood- -zakelijk gehonoreerd. Dit is het geval als de interrupts uit -staan (DI). - -Indien er twee interrupts optreden van dezelfde bron terwijl -de eerste nog niet gewist is door de CPU, dan zal de tweede -verloren gaan. Deze situatie komt echter ERG weinig voor. - -Als de interrupt gehonoreerd wordt, zal hardwarematig een DI -gegeven worden en het is aan de schrijver van de ISR om weer -een EI te geven (aan het eind van de routine bv.) Het is -mogelijk dat een interrupt geaccepteerd wordt terwijl de -interrupts uit staan. - -Bij een normale INT zal er naar adres 38H gesprogen worden. - -De bron van de int. zal zo snel mogelijk verteld moeten -worden dat de int. geaccepteerd is. De manier van de VDP die -het INT bit zelf wist als S#0 gelezen wordt is trouwens heel -standaard. De meeste chips die interrupts kumnen genereren -werken op deze manier omdat het makkelijk en snel is. - -Als een EI instruktie gegeven wordt zullen de interrupts -niet meteen aktief worden. Ze worden feitelijk pas -ingeschakeld na de instruktie die op de EI volgt. Op deze -manier kan je dus eerst nog een RET doen na een EI voordat -een geaccepteerde int. gehonoreerd wordt. - - -## N M I - -De Z80 heeft echter nog een interrupt die bij alle modes -aanwezig is, maar die op de MSX niet aangesloten is. Het is -de Non Maskable Interrupt die op bijna elke processor te -vinden is en ook meestal dezelfde naam heeft. Deze interrupt -is niet uit te zetten en heeft de op ��n na hoogste -prioriteit van alle interrupts. Als een NMI en een INT -tegelijkertijd optreden, dan zal eerst de NMI afgehandeld -worden. Omdat de NMI niet uit te zetten is zal een NMI -altijd meteen gehonoreerd worden tenzij er een busrequest -optreedt (dit is nl. ook een soort int. maar deze heeft de -allerhoogste prioriteit). - -Als een NMI optreedt, dan zal de Z80 zelf een DI uitvoeren, -maar hij bewaart de stand van de ints op het moment van -acceptatie. Na afhandeling van de NMI (die naar adres 66H -springt) zal de Z80 zelf de interrupt status terugzetten. -Als de ints dus uit stonden voordat de NMI optrad, dan -blijven ze ook uit na de afhandeling van de NMI en andersom. -De NMI moet afgesloten worden met de RETN instruktie en niet -met een RET omdat een RETN die oude int. status hersteld. -Bij een normale int. mag je geen RETN geven, want dat heeft -geen zin en kan alleen tot fouten leiden. - -Een vriend van me heeft al eens een schakelaar op de NMI -aangesloten en dat werkt prima. Hij kan dus met een druk op -de knop een routine starten die hij zelf eerst op de NMI -HOOK heeft gezet. Dit is erg leuk, maar het kan bij het -laden van disk problemen veroorzaken. Voor de hardwaremannen -onder ons is het toch een leuk en simpel projekt om eens te -doen. - - -## R E T I - -Veel mensen weten van het bestaan van deze instruktie, maar -er zijn er maar weinig die weten waar hij voor dient. Welnu, -deze instruktie is helemaal gelijk aan een normale RET -instruktie met het verschil dat hij een andere OPCODE heeft. -Zo zou een randapparaat dus kunnen kijken wanneer de CPU -klaar is met het afhandelen van een ISR door de databus te -scannen. Deze methode is bij mijn weten nog nooit gebruikt. -Het gebruik ervan is echter best handig omdat je zo heel -snel een ISR routine kunt herkennen. - - -## E I O F D I - -Heb je dat nu ook wel eens dat je wilt weten of op een -bepaald moment de ints aan of uit staan ?? Lang werd er -gedacht dat dit niet te testen is, maar dat is niet waar. -Het volgende programma kan dit testen: -``` - LD A,R ; Het werkt ook met LD A,I - PUSH AF - POP BC - BIT 2,C - JR Z,INTUIT -INTAAN: . - . -``` -In bit 2 van het F-register staat na een LD A,R de inhoud -van de IFF flip-flop. Dit bit wordt 0 gemaakt bij een DI -instruktie en 1 bij een EI. - - -## D E E I G E N I S R - -Om een kompleet eigen ISR te kunnen schrijven is het nodig -om de BIOS weg te halen en deze door RAM te vervangen. Zo -kan je zelf bepalen wat er vanaf adres 38H komt te staan, -maar voor de rest is het precies hetzelfde principe als bij -de normale MSX-ISR. Deze methode heeft alleen maar zin als -je HEEEL snel op een int. wilt reageren (bv. als je 40 -screensplits op je scherm wilt toveren). Je kunt nl. -beslissen om alleen de registers te PUSHen die je gaat -veranderen en niet de hele meute zoals de standaard ISR -doet. - - -## S L I M M E T R U C - -Bij screensplits is het te voorspellen welke screensplit aan -de beurt is door een soort tellertje bij te houden. Stel je -nu eens voor dat je meerdere ISR's hebt die aangeroepen -moeten worden voor de verschillende screensplits. Als er nu -eens een manier was om voordat een int. optreedt vast te -stellen waar deze heen moet springen (als deze uiteindelijk -optreedt) dan zou dat een behoorlijke respons snelheidswinst -betekenen. Het enige probleem dat hierbij om de hoek komt -kijken is de ISR zelf. Het adres waar heen gesprongen moet -worden staat in het RAM. Dus deze waarde moet ingelezen -worden, maar hoe doe je dat nu zonder uiteindelijk een -register te veranderen (iets dat immers niet mag in een ISR) -Welnu, laat ik eerst maar de oplossing geven en daarna nog -wat verdere uitleg. -``` -0038H PUSH HL -0039H LD HL,(ISRPNT) ; De ISR pointer -003CH EX (SP),HL -003DH RET - -00F0H ISRPNT: DW &HFD9A ; Het pointeradres -``` -HL moet op de stack gezet worden omdat je anders de pointer -niet uit kan lezen. De EX (SP),HL draait de pointer en de -oude waarde van HL echter om zodat het programma ook te -beschrijven is als: -``` - PUSH (ISRPNT) - RET -``` -of: -``` - JP (ISRPNT) -``` -Deze laatste twee oplossingen kunnen echter niet -gerealiseerd worden omdat de Z80 deze instrukties niet kent. -In principe doen ze echter hetzelfde. Het resultaat van dit -alles is dus dat je voordat een int. optreedt kunt bepalen -waar deze heen moet springen en deze sprong uit kunt voeren -zonder een register van waarde te veranderen. De RET -instruktie van de echte oplossing verhoogt de SP immers ook -weer naar zijn oude waarde, dus het enige dat verandert is -de PC (Program Counter) en dat was nu juist de bedoeling. - -De responstijd is zo goed omdat je weet welke en wat voor -interrupt op zal gaan treden zodat je ook het feitelijke -pollen kunt doen voordat de int. optreedt. Als er dan -uiteindelijk een int optreed hoef je alleen nog maar naar de -juiste ISR te springen en is alle informatie al voorbereid. -Je moet echter goed oppassen dat je de tel niet kwijt raakt -omdat het dan dus echt een puinhoop wordt. Zorg er dus voor -dat de ints. zoveel mogelijk aan staan (ook om de -responstijd hoog te houden). - - -## D E F E I T E L I J K E I S R - -Hier is nu nog maar weinig over te vertellen. Het enige dat -je hier extra moet doen t.o.v. de standaard ISR is het -PUSHen van registers die je gaat veranderen oftewel: -``` -0038H JP ISR - -0100H ISR: PUSH AF - PUSH xx - . - IN A,(&H99) ; Is het een 50/60 Hz signaal?? - . - . - POP xx - POP AF - RET ; Einde van int. afhandeling -``` - -## B I O S W E G ? ? - -Dat is heel simpel met de volgende routine: -``` - LD A,(&HF341) - LD H,0 - CALL &H24 ; Zet RAM over BIOS - LD A,RAMPGE - OUT (&HFC),A - [ Initialiseer de ISR ] - EI -``` -Nu staat mapper page RAMPGE vanaf adres 0000H tot 3FFFH. Je -hoeft nu alleen nog maar de ISR af te buigen en je bent -klaar voor aktie. Na een CALL op adres &H24 staan de -interupts overigens uit, en het is aan de gebruiker om deze -daarna weer aan te zetten. - -Goed, de eigen ISR is ge�nstalleerd, maar hoe krijgen we nu -de BIOS weer terug?? Met CALL &H24 gaat dat niet, want die -is immers weggehaald!! Het zelf schakelen van sloten is een -mogelijkheid, maar er is een simpeler manier. Op deze disk -staat de assembly listing "ENASLT.ASM" waar de complete CALL -&H24 in nagemaakt is. Voeg deze routine simpelweg aan je -eigen programma toe en gebruik hem inplaats van CALL &H24. -Alle schakelproblemen zouden dan opgelost moeten zijn. Om de -BIOS weer terug te krijgen moet je het volgende intikken. -``` - LD A,(&HFCC1) - LD H,0 - CALL ENASLT ; Dus niet CALL &H24 -``` - -Hopelijk zijn jullie iets nieuws te weten gekomen uit deze -informatie en moet het mogelijk zijn om eens lekker ISR's te -kunnen gaan maken. Het resultaat zie ik dan wel op bv. de -Sunrise Picturedisk!! - -Alex van der Wal diff --git a/Sunrise Special/2/MSX-DOS 2 voor machinetaalprogrammeurs.md b/Sunrise Special/2/MSX-DOS 2 voor machinetaalprogrammeurs.md deleted file mode 100644 index 178efe5..0000000 --- a/Sunrise Special/2/MSX-DOS 2 voor machinetaalprogrammeurs.md +++ /dev/null @@ -1,428 +0,0 @@ -# C U R S U S M S X - D O S 2 V O O R M A C H I N E T A A L P R O G R A M M E U R S - - -Op deze Sunrise Special start ik een cursus waarin ik de -vele mogelijkheden van MSX-DOS 2 zal beschrijven. Ik zal -proberen door middel van voorbeelden de nieuwe DOS-CALL's -duidelijk te maken. De cursus zal uit ongeveer zes delen -bestaan met op deze disk het eerste deel. In dit eerste deel -zal ik de programma-omgeving beschrijven die MSX-DOS 2 voor -programma's biedt. - - -## H E T T P A - G E H E U G E N - -TPA staat voor Transient Program Area. Een Transient Program -(TP) is een moeilijk woord voor een normale COM-file. Deze -COM-files worden door COMMAND2 ingeladen op adres #0100 en -vervolgens geCALLed met de stackpointer (SP) aan het einde -van het TPA. Al het geheugen tot aan de stack mag gebruikt -worden door het TP. De inhoud van de Z80-registers is niet -gedefinieerd. De eerste 256 bytes van het RAM hebben een -speciale betekenis. Deze bytes zal ik dadelijk verklaren. -Interrupts staan aan als een TP aangeroepen wordt door -COMMAND2 en moeten in het algemeen aan blijven staan. -MSX-DOS function-calls zullen meestal de interrupts -aanzetten als ze uitstonden. - - -## T E R U G K E E R N A A R M S X - D O S - -Een TP kan zichzelf be�indigen door middel van een van de -onderstaande manieren: - -1 Terugkeren d.m.v. RET, met de originele SP. -2 JumP naar adres #0000. -3 MSX-DOS "Program Terminate" function call. -4 MSX-DOS 2 "Terminate with Error Code" function call. - -De eerste drie zijn identiek met CP/M en MSX-DOS 1. De -laatste is een nieuwe functie van MSX-DOS 2. Met deze -functie kan een programma een foutmelding teruggeven aan -COMMAND2 die deze zal afdrukken op het standaard device CON -(NvdR: Hoeft niet per se CON te zijn, kan ook PRN of NUL -zijn). Deze functie zal geen foutmelding afdrukken als de -error code gelijk is aan nul. Vele andere acties kunnen het -programma dwingen af te breken, waaronder onder andere het -drukken van CTRL-C, CTRL-STOP of het kiezen van de optie -Abort als er een diskerror optreedt. Een TP kan een "abort -routine" definieren, die deze gevallen kan opvangen. - - -## A D R E S # 0 0 0 0 T O T # 0 1 0 0 - -In de eerste 256 bytes van het geheugen worden door COMMAND2 -enige parameters gezet voor het TP. De indeling van deze -eerste bytes is als volgt. -``` - +0 +1 +2 +3 +4 +5 +6 +7 - +-----+-----+-----+-----+-----+-----+-----+-----+ -#0000 | Reboot Entry | Reserved | MSX-DOS Entry | - +-----+-----+-----+-----+-----+-----+-----+-----+ -#0008 | RST #08: ongebruikt | RDSLT routine Entry | - +-----+-----+-----+-----+-----+-----+-----+-----+ -#0010 | RST #10: ongebruikt | WRSLT routine Entry | - +-----+-----+-----+-----+-----+-----+-----+-----+ -#0018 | RST #18: ongebruikt | CALSLT routine Entry | - +-----+-----+-----+-----+-----+-----+-----+-----+ -#0020 | RST #20: ongebruikt | ENASLT routine Entry | - +-----+-----+-----+-----+-----+-----+-----+-----+ -#0028 | RST #28: ongebruikt | ongebruikt | - +-----+-----+-----+-----+-----+-----+-----+-----+ -#0030 | CALLF routine entry | ongebruikt | - +-----+-----+-----+-----+-----+-----+-----+-----+ -#0038 | Interrupt vector | | - +-----+-----+-----+-----+ + -#0040 | | - + + -#0048 | Gebruikt door slot switching code | - + + -#0050 | | - + +-----+-----+-----+-----+ -#0058 | | | - +-----+-----+-----+-----+ + -#0060 | Ongeopend FCB van de eerste parameter | - + +-----+-----+-----+-----+ -#0068 | | | - +-----+-----+-----+-----+ | -#0070 | Ongeopend FCB van de tweede parameter | - + +-----+-----+-----+-----+ -#0078 | | Ruimte voor FCB-data | - +-----+-----+-----+-----+-----+-----+-----+-----+ -#0080 | | - . . - . Default DMA-adres . - . Hier staat de originele commando line . - . . - . . -#00F8 | | - +-----+-----+-----+-----+-----+-----+-----+-----+ -``` -Op adres #0000 staat de jump, die gebruikt wordt voor het -be�indigen van een programma. Deze jump kan ook gebruikt -worden om de BIOS jump vector te vinden. (Zie verderop). De -lage byte van dit adres zal altijd #03 zijn voor de -compatibiliteit met CP/M. - -De twee gereserveerde bytes op adres #0003 en #0004 zijn de -IO-byte en de Current Drive/User byte in CP/M. Hoewel -MSX-DOS 2 deze byte altijd up-to-date houdt, wordt het niet -aanbevolen om in nieuwe programma's deze byte te gebruiken. -Deze kunnen beter de MSX-DOS 2 function call "Get current -drive" gebruiken. Het IO-byte wordt niet ondersteund, omdat -MSX-DOS 2 device-IO anders geregeld heeft dan CP/M. - -Op adres #0005 staat een jump naar de start van de -BDOS-verwerking van MSX-DOS 2. Dit jumpadres bepaalt de top -van het TPA. De grootte van het TPA hangt af van de -uitbreidingen die u gebruikt, maar is standaard 53 kB. De -lage byte van dit adres zal altijd #06 zijn voor de -compatibiliteit met CP/M. De zes bytes direct hierachter -bevatten het CP/M-versienummer en een serienummer. - -Er zijn vier bytes gereserveerd voor de gebruiker op elk -Z80-restart adres. De bytes tussen de restart adressen zijn -entry's voor enkele MSX slot switching routines. - -Het hele gebied van #0038 tot #005C wordt gebruikt voor de -interruptafhandeling in slot switching code. - -De twee FCB's op adres #005C en #006C zijn de eerste twee -parameters achter de commandonaam, gezien als filenamen. Als -beide FCB's gebruikt worden moet de tweede naar een andere -locatie gekopieerd worden, want als de eerste geopend wordt, -zal die de tweede overschrijven. - -De gehele commandoline, zonder commandonaam, wordt bewaard -in het standaard DMA gebied (vanaf #0080) met als eerste -byte een lengtebyte en als laatste byte een nul. (Noch de -lengtebyte noch de nul worden meegeteld in de lengte). De -commandoline zal geheel uit hoofdletters bestaan als het -environment item "UPPER" op "ON" gezet is. De commandoline -zal niet ontdaan worden van inleidende spaties. - -Nieuwe programma's kunnen de oude FCB's beter niet meer -gebruiken. Er zijn in MSX-DOS 2 andere, simpelere functies -beschikbaar. Deze functies maken het ook mogelijk met -subdirectory's te werken. - -Er is nog een manier om de commandoline uit te lezen. -COMMAND2 zet namelijk een environment item, "PARAMETERS" -genaamd, op die de commandoline bevat in zijn originele -staat. Het tweede environment item dat COMMAND2 op zet heet -"PROGRAM". Dit bevat het Drive\Path\Filenaam string dat gold -voor het geladen programma. - - -## D E B I O S J U M P T A B L E - -De jump op adres #0000 zal springen naar een adres dat ook -een jump bevat. Deze jump is de tweede entry in een jump -table van zeventien entry's. Dit komt exact overeen met -CP/M. - -De eerste acht entry's zijn voor reboot en karakter-IO. De -andere negen doen niets en geven, waar mogelijk, een -errorcode terug. - -MSX-DOS 2 zal bij een CALL overschakelen naar een interne -stack, zodat de userstack niet groter hoeft te zijn dan -ongeveer acht bytes. - -Overzicht BIOS jumptable: -``` -#xx00 Warm boot -#xx03 Idem -#xx06 Console status -#xx09 Console input -#xx0C Console output -#xx0F List output -#xx12 Punch output -#xx15 Reader input -#xx18 Geen functie -#xx1B Geen functie -#xx1E Geen functie -#xx21 Geen functie -#xx24 Geen functie -#xx27 Geen functie -#xx2A Geen functie -#xx2D List status -#xx30 Geen functie -``` - -## G E H E U G E N G E B R U I K - -Een TP mag zoveel slotswitching doen als het wil, als het -maar rekening houdt met de interrupts e.d. als het TP page -nul of drie wegschakelt. TP's moeten erg voorzichtig zijn -met het veranderen van page 0 en TP's mogen nooit -veranderingen aanbrengen in page 3. Page 0, 1 en 2 mogen in -elk slot zitten als het TP MSX-DOS 2 aanroept. Deze -instellingen zullen bewaard blijven. Een parameter kan via -elk slot aan MSX-DOS 2 worden doorgegeven. Dit geldt niet -voor de environmentstrings en de diskbuffers. Deze moeten -zich in de main mapper bevinden. Het is mogelijk om gegevens -in andere segmenten dan de originele TPA segmenten te laden. -Als het TP de memory mapper wil schakelen moet het daarvoor -gebruik maken van de mappersupportroutines in page 3. Deze -routines zal ik de volgende keer beschrijven. Een TP dat de -mapper schakelt moet er zelf voor zorgen dat de originele -TPA segmenten weer ingeschakelt worden, als het programma -eindigt. - - -## F I L E H A N D L E S - -File handles zijn de nieuwe verbeterde methoden om files aan -te spreken en te manipuleren. Een file handle is een byte -die betrekking heeft op een geopende file. Er wordt een -nieuwe file handle aangemaakt bij de aanroep van de MSX-DOS -2 functie "Open file handle" (#43) of "Create file handle" -(#44). De file handle kan gebruikt worden om data van de -file te lezen of data naar de file te schrijven. Een file -handle blijft bestaan totdat een van de volgende MSX-DOS 2 -functies wordt gebruikt: "Close file handle" (#45) of -"delete file handle" (#46). MSX-DOS 2 opent als het opstart -al enige file handles voor de standaard IO-kanalen. Deze -default file handles zijn: -``` -#00 Standaard input (CON) -#01 Standaard output (CON) -#02 Standaard error in/output (CON) -#03 Standaard auxiliary in/output (AUX) -#04 Standaard printer output (PRN) -``` -Een TP mag deze file handles sluiten, verwijderen of op een -andere manier beschadigen, omdat COMMAND2 deze file handles -automatisch zal herstellen. Ook als een TP zich niet netjes -gedraagt en niet alle file handles sluit, zal dit geen -probleem opleveren, omdat COMMAND2 dit zal doen. (Netjes is -anders). - - -## F I L E I N F O B L O C K S ( F I B ) - -Alle nieuwe MSX-DOS 2 functies die op files werken, kunnen -aangeroepen worden met een simpele pointer naar een string. -Deze string bevat dan de benodigde parameters afgesloten -door een nul. Dit soort strings noemt men ASCIIZ-strings. In -plaats van een ASCIIZ-string mag men ook een FIB doorgeven -aan MSX-DOS 2. FIB's zien er als volgt uit: -``` - 0 - Altijd #FF - 1..13 - Filename als ASCIIZ-string - 14 - File atributen -15..16 - Tijd -17..18 - Datum -19..20 - Eerste datacluster -21..24 - Grootte van de file - 25 - Logische drive (A: = 1) -26..63 - Interne informatie -``` -De #FF aan het begin van een FIB is als herkenning voor het -systeem dat het om een FIB gaat en niet om een platte -ASCIIZ-string. De interne informatie vanaf byte 26 mag nooit -verandert worden. De byte van de file atributen ziet er zo -uit: -``` -Bit 0 Read only -Bit 1 Hidden -Bit 2 System -Bit 3 Volume naam -Bit 4 Directory -Bit 5 Archive -Bit 6 Gereserveerd -Bit 7 Device -``` -De tijd en datum moet men zo coderen: -Tijd: Bits 15..11 Uren (0..23) - Bits 10...5 Minuten (0..59) - Bits 4...0 Seconden (0..58, even getallen) -Datum: Bits 15...9 Jaar (0..99, 1980 tot 2080) - Bits 8...5 Maand (1..12) - Bits 4...0 Dag (0..31) - -De filegrootte wordt opgeslagen als een 32-bit getal met de -lowbyte eerst. Deze byte is nul voor directory's. Deze FIB's -worden door de functie calls "Find first entry", "Find next -entry" en "Find new entry" ingevuld. - - -# F I L E C O N T R O L B L O C K S ( F C B ) - -Een FCB is 32 bytes lang en bevat de volgende informatie: -``` - #00 Drive nummer (A:=1, Default=0) -#01..#08 Filename -#09..#0B Filename extensie - #0C Bloknummer - #0D Attributen -#0E..#0F Record-lengte -#10..#13 Filegrootte -#14..#17 Volume-ID (DOS 2) Time/Date (DOS 1) -#18..#1F Interne informatie - #20 Current record -#21..#24 Random recordnummer -``` -Het wordt niet aanbevolen om deze verouderde manier van -fileacces nog te gebruiken. Men kan onder MSX-DOS 2 beter de -file handles gebruiken. Deze laatste kunnen ook met -directory's werken en dat kunnen FCB's niet. - - -## F O U T M E L D I N G E N - -MSX-DOS 2 kan vele foutmeldingen teruggeven. Deze hebben -alle een nummer tussen #FF en #00. De complete lijst (?) van -foutmeldingen volgt nu: - -Nummer Melding -``` -#FF Incompatible disk. -#FE Write error -#FD Disk error -#FC Not ready -#FB Verify error -#FA Data error -#F9 Sector not found -#F8 Write prtected disk -#F7 Unformatted disk -#F6 Not a DOS disk -#F5 Wrong disk -#F4 Wrong disk for file -#F3 Seek error -#F2 Bad file allocation table -#F1 - -#F0 Cannot format this drive -#EF - . - . Niet gebruikt - . -#E0 -#DF Internal error -#DE Not enough memory -#DD - -#DC Invalid MSX-DOS call -#DB Invalid drive -#DA Invalid filename -#D9 Invalid pathname -#D8 Pathname too long -#D7 File not found -#D6 Directory not found -#D5 Root directory full -#D4 Disk full -#D3 Duplicate filename -#D2 Invalid directory move -#D1 Read only file -#D0 Directory not empty -#CF Invalid attributes -#CE Invalid . or .. operation -#CD System file exists -#CC Directory exists -#CB File exists -#CA File already in use -#C9 Cannot tranfer above 64K -#C8 File alloccation error -#C7 End of file -#C6 File acces violation -#C5 Invalid process ID -#C4 No spare file handles -#C3 Invalid file handle -#C2 File handle not open -#C1 Invalid device operation -#C0 Invalid environment string -#BF Environment string too long -#BE Invalid date -#BD Invalid time -#BC RAM disk already exists -#BB RAM disk does not exist -#BA File handle has been deleted -#B9 - -#B8 Invalid sub-function number -#B7 - . - . Niet gebruikt - . -#A0 -#9F Ctrl-STOP pressed -#9E Ctrl-C pressed -#9D Disk operation aborted -#9C Error on standard output -#9B Error on standard input -#9A - . - . Niet gebruikt - . -#90 -#8F Wrong version of COMMAND -#8E Unrecognized command -#8D Command too long -#8C - -#8B Invalid parameter -#8A Too many parameters -#89 Missing parameter -#88 Invalid option -#87 Invalid number -#86 File for HELP not found -#85 Wrong version of MSX-DOS -#84 Cannot concatenate destination file -#83 Cannot create destination file -#82 File cannot be copied onto itself -#81 Cannot overwrite previous destination file -#80 - . - . Niet gebruikt - . -#00 -``` - -De hierboven met "niet gebruikt" aangegeven codes geven -meestal een system of user error xx. - -Zo dat was het voor deze keer. Allemaal een beetje saai en -droog. De volgende keer zal ik de mapper support routines en -een gedeelte van de function-calls bespreken. Ik zal er dan -enige voorbeelden bij doen zodat u niet helemaal in slaap -valt. - -Daniel Wiermans \ No newline at end of file diff --git a/Sunrise Special/2/MSX-DOS 2.31.md b/Sunrise Special/2/MSX-DOS 2.31.md deleted file mode 100644 index fef7cf3..0000000 --- a/Sunrise Special/2/MSX-DOS 2.31.md +++ /dev/null @@ -1,186 +0,0 @@ -# M S X - D O S 2 . 3 1 - - -Bij de Panasonic FS-A1GT wordt MSX-DOS 2.31 geleverd in het -ROM. Veel mensen denken dat DOS 2.31 alleen zorgt voor de -ROM- en SRAMdisk, en dus voor MSX-View. Dat bleek toch niet -waar te zijn: - - -## S R A M D I S K Z O N D E R M S X - V I E W - -Veel mensen vroegen zich (en anderen...) af hoe ze de -SRAMdisk van de GT konden gebruiken zonder MSX-View van de -ROMdisk op te hoeven starten. -Door mijn nieuwsgierige aard heb ik even TYPE C:AUTOEXEC.BAT -ingetikt bij een GT-user. Wat ik daar zag was natuurlijk een -opluchting voor de GT'er: -IF EXIST %SRAMD%\AUTOEXEC.BAT %SRAMD%\AUTOEXEC.BAT - -In menselijke taal wordt dat: -Als de file AUTOEXEC.BAT op de SRAMdisk staat, moet die -batchfile uitgevoerd worden. - -De mensen die bovenstaande vraag hadden, kunnen zich nu voor -het hoofd slaan, of natuurlijk gewoon een file genaamd -AUTOEXEC.BAT op de SRAMdisk plaaten. -Op deze disk staat een file die ook in BBS'en heeft gestaan. -De file schakelt de ROM-mode en copieert de Europese -karakterset naar het RAM. En dan wordt weer teruggeschakeld -naar DRAM-mode. - -De werking is als volgt: Bij een reset worden de systeemROMs -naar RAM gecopieerd, door naar de ROM-mode te schakelen -worden die RAM-pagina's weer vrijgegeven voor "hardnekkige" -software. De BIOS wordt vervolgens aangepast door de -Europese karakterset te copi�ren over de Japanse karakterset -heen. Dan wordt de DRAM-mode teruggeschakelt, en worden de -ROMs niet meer over de RAM heengecopieerd. Dit programma -leent zich uitstekend om op de SRAMdisk gezet te worden. Dat -staat ook in DOS231.PMA. - -Met "hardnekkige" software bedoel ik software die niet -volgens de standaard MSX-DOS 2 mapperroutines werkt. -Eigenlijk moeten die memory mapper plaatsen worden -vrijgegeven met FreSEG. Op deze disk staat een programmaatje -uit MSX-Magazine 1 van 1990 genaamd ROMTURBO.COM. Door dit -te runnen wordt de ROM-mode ingeschakeld en de -mappersegmenten die eerst door de DRAM werden gebruikt weer -vrijgegeven. Voor meer informatie over DRAM-mode raad ik aan -om Sunrise Special #1 nog eens te lezen, en dan vooral het -artikel over de R800. -N.B. Het broertje van ROMTURBO, RAMTURBO, staat ook op deze -disk. - - -## E N V I R O N M E N T I T E M S - -DOS 2.31 kent de mijns inziens zeer interessante -mogelijkheid om Environment Items (vanaf nu gewoon items) te -gebruiken in batchfiles. - -Je kunt dan, zij het zeer beperkt, programmeren in -batchfiles. Een zeer simpel virus zou mogelijk zijn. -Het benoemen van items zal iedereen wel duidelijk zijn nu. -Dat gaat gewoon met SET. Voorbeelden volgen zometeen. - -Maar je kunt ze nu ook gebruiken voor alle andere -doeleinden: Gewoon laten voorgaan en volgen door een -%-teken. Je krijgt dan bijv. %SRAMD% voor drivenaam die de -SRAMdisk heeft. Dat kun je dus ook veranderen met SET. (SET -SRAMD=drivenaam:). (Nee, geen dwerg-smiley, maar een dubbele -punt.) - - -## I F - -Met IF == kun je tekst vergelijken. Tekst vergelijken is -niet echt zo interessant. Maar de kracht van deze functie is -dat items met %-tekens eromheen als tekst gezien worden in -batchfiles. -Je kunt ook kijken of een file wel bestaat: - - -## E X I S T - -Met IF EXIST kun je erachter komen of een bepaalde file -bestaat. Bovenaan, in de regel uit AUTOEXEC.BAT van de -ROMdisk, staat het ook al. De werking is zeer simpel. Als -een file bestaat wordt gewoon het commando wat erop volgt -uitgevoerd. De file volgt gewoon achter IF EXIST. - - -## N O T - -Met NOT geef je een negatie aan. Je kunt dus IF NOT EXIST -filenaam.ext enz. gebruiken. - - -## E E N V O O R B E E L D - -Ik gebruik zelf een paar leuke batchfiles om mijn leven als -HD-gebruiker te vergemakkelijken. Als je maar weinig -opslagruimte hebt, heeft het eigenlijk weinig nut. Meestal -doe je dan toch weinig in DOS. Maar voor een HD-user die -GUI's niet handig vindt, wordt het allemaal wat aangenamer -met batchfiles. Bij een Turbo R zul je het nauwelijks -merken, maar bij een 3.58 MHz Z80 zal de snelheid flink -afnemen door het gebruik van deze batchfile. Voor 7 -MHz-gebruikers zal het nog wel te doen zijn. - - -## T E D . B A T - - CLS - -Schoon scherm. Ligt aan je persoonlijke wensen. - - IF NOT %1NIKS==NIKS SET TEDFILE=%1 - -Als %1 plus NIKS NIET gelijk is aan niks, wordt TEDFILE aan -%1 gelijk gemaakt. Zorgt ervoor dat de naam hetzelfde blijft -als je geen parameter opgeeft. Zeer handig bij het debuggen -van een machinetaalprogramma! - - IF NOT EXIST %TEDFILE% SET TEDFILE= - -Als %TEDFILE% NIET bestaat wordt %TEDFILE% gewist. - - IF EXIST %TEDFILE%.MAC SET TEDEXT=.MAC>NUL - IF EXIST %TEDFILE%.GEN SET TEDEXT=.GEN>NUL - IF EXIST %TEDFILE%.BAT SET TEDEXT=.BAT>NUL - IF EXIST %TEDFILE%.DOC SET TEDEXT=.DOC>NUL - IF EXIST %TEDFILE%.TXT SET TEDEXT=.TXT>NUL - -Er wordt gekeken of de file bestaat met een van de 5 -extensies. Dit is natuurlijk naar wens in te stellen. Het -gaat trouwens van minst belangrijke naar belangrijkste. Als -er bijv. een .GEN- en een .DOC-file bestaan wordt de -.DOC-file ingeladen. Die staat immers iets lager. ->NUL wordt opgegeven om de evt. foutmeldingen niet op het -scherm te laten komen. Zie voor meer uitleg de tekst over -redirection en pipelining op deze disk. - - SET TEDEXE=A:\TED\TED.COM - IF %TEDEXT%==.MAC SET %TEDEXE%=A:\TED\MLTED.COM - IF %TEDEXT%==.GEN SET %TEDEXE%=A:\TED\MLTED.COM - %TEDEXE% %TEDFILE%%TEDEXT% - -Het opstarten van TED. Voor %TED% is de directory plus de -naam die TED heeft. Door deze constructie te gebruiken kun -je verschillende versies van TED gebruiken, die je met -hetzelfde commando opstart. MLTED is bij mij een versie met -de instellingen (zoals TAB's) ingesteld voor machinetaal. -Als TED.BAT en TED.COM in dezelfde directory staan zal -TED.COM worden ingeladen als het commando "TED" wordt -ingetikt. Daarom MOET TED.COM in een andere directory staan -als deze batchfile gebruikt worden. Of je moet iedere keer -TED.BAT filenaam intikken. En het was nu juist om het -makkelijker te maken. Je kunt natuurlijk ook, om het -helemaal makkelijk te maken de batchfile T.BAT noemen. Dan -hoef je maar een letter in te tikken als je net uit TED zelf -komt. - - -Op deze disk staan: - -ROMTURBO.COM Programma om de 64 kB RAM die de DRAM-mode - inpikt toch te kunnen gebruiken. Dit gaat - volgens de standaard: De segmenten die door de - DRAM-mode worden gebruikt worden met de - standaard MSX-DOS 2 mapper-routines - vrijgegeven. - -RAMTURBO.COM Programma dat de DRAM-mode volgens de - standaard installeert. Als er niet genoeg - geheugen meer is, wordt een melding gegeven. - -KARSET.COM Programma dat de Europese karakterset in de - DRAM zet. Er zit geen puntje, maar een - streepje door de nul. In de oorspronkelijke - versie was het een puntje. - -TED.BAT De batchfile van het voorbeeld. - - -Kasper Souren \ No newline at end of file diff --git a/Sunrise Special/2/Macro commandos met gen80.md b/Sunrise Special/2/Macro commandos met gen80.md deleted file mode 100644 index 030e847..0000000 --- a/Sunrise Special/2/Macro commandos met gen80.md +++ /dev/null @@ -1,258 +0,0 @@ -# M A C R O C O M M A N D O - S M E T G E N 8 0 - - -## W A T I S E E N M A C R O ? - -Je kunt macro's gebruiken om je assemblercode een stuk -flexibeler en overzichtelijker te maken. Een macro kun je -zien als een extra commando dat door de assembler in een -aantal andere instructies wordt omgezet. - -Nu zeg je: Dat is toch onzin. Het is toch veel duidelijker -om gewoon de instructies te gebruiken. Ja, dat kan ook wel -zo zijn, maar als je 10 keer dezelfde instructie moet -gebruiken en een CALL is niet handig of mogelijk, is het -gebruik van macro's een mooi alternatief. En het is nog -makkelijk aan te passen ook. - -Noot: Alleen GEN80 en Microsoft M80 werken, voor zover ik -weet, met macro's. WBASS2-gebruikers kunnen of deze tekst -niet lezen of een andere assembler gaan aanschaffen. - - -## H E T G E B R U I K - -Met macro's is het omzetten van de source van een BLOAD-file -naar een .COM-file een koud kunstje. Het label BDOS had je -natuurlijk al aan het begin gedefinieerd met -``` - BDOS: EQU #F37D -``` -en dan hoef je #F37D alleen maar in het begin te veranderen -in 5 (of andersom als je van MSX-DOS naar BASIC wil). - -Maar dan moet je ook de BIOS-commando's omzetten. Meestal is -dat dan een kwestie van zoeken en vervangen (in TED). Maar -als je macro's gebruikt had was het een karweitje van ��n -twaalfhonderdste uur (oftewel 3 seconde) geweest. - -Ik gebruik in mijn eigen sources altijd ��n van de volgende -macro's: -``` - BIOS: MACRO @FNC ;Voor MSX-DOS - LD IX,@FNC - LD IY,(#FCC0) - CALL #001C - ENDM - - BIOS: MACRO @FNC ;Voor BASIC - CALL @FNC - ENDM -``` -Het is dan een koud kunstje om een BIOS-funktie aan te -roepen vanuit een .COM-file. En last but not least, het -wordt een heel stuk duidelijker: -``` - LD IX,#0180 - LD IY,(#FCC0) - CALL #001C -``` -of -``` - BIOS #0180 -``` - -## C O M M A N D O - S - -Ik werk zelf alleen nog maar met GEN80. (Ik heb eerst met -WBASS2 gewerkt, maar toen ik GEN80 door had, was ik -verkocht.) Ik bespreek dit dan ook met de commando's en -voorbeelden die in de handleiding van GEN80 staan. M80 -werkt, denk ik, precies hetzelfde, maar je weet maar -nooit... - -Uit het bovenstaande voorbeeld zal grotendeels duidelijk -zijn hoe een macro moet worden gedefinieerd. Maar voor de -zekerheid staat het hieronder iets beter. - -MACRO: De naam van het macro geef je op aan het begin van - de regel. Dan zet je daar MACRO achter en de - eventuele te gebruiken variabelen: - - [macro] MACRO @var1(,@var2,...,@varX) - - De variabelen met een apestaartje ("@") erin, zijn - lokale variabelen. Die komen verder ook niet in de - .SYM-file terecht en worden alleen gebruikt als - input. - -ENDM: Je be�indigt een macro met het commando ENDM, dat - (natuurlijk) staat voor END of Macro. - -DEFL: Met DEFL kan een label een waarde worden gegeven IN - een macro. - -IF: Met IF kun je voorwaardelijk assembleren. Als de - waarde van de uitdrukking ongelijk aan 0 is worden - de instructies op de regels na IF uitgevoerd tot aan - ELSE of ENDC. - IFs zijn nestbaar tot een diepte van 8. -COND: Gelijk aan IF. - -ELSE: Dit commando komt voor ENDIF en na IF. Als de - uitdrukking achter IF wel 0 is, worden de commando's - op de regels na ELSE uitgevoerd tot aan ENDIF. - -ENDC: Dit geeft het einde van een voorwaardelijk gedeelte - aan. -ENDIF: Gelijk aan ENDC. - - -## V O O R B E E L D E N - -Alle voorbeelden staan ook in de file MACRO.LIB. Je kunt dan -de macro's die je nodig hebt daaruit halen. -De volgende voorbeelden komen uit de handleiding van GEN80: -``` - BC_DE: MACRO @PARAM1, @PARAM2 - LD BC,@PARAM1 - LD DE,@PARAM2 - ENDM -``` -De instructie -``` - BC_DE #4444,-5 -``` -zal door GEN80 worden omgezet in de assembler-instructies -``` - LD BC,#4444 - LD DE,-5 -``` - -## E X C H A N G E -``` - EXCH: MACRO @REG1,@REG2 - IF @REG1=HL .AND. @REG2=DE - EX DE,HL - ELSE - IF @REG1=DE .AND. @REG2=HL - EX DE,HL - ELSE - PUSH @REG1 - PUSH @REG2 - POP @REG1 - POP @REG2 - ENDIF ;Niet vergeten! - ENDM -``` -Er wordt eerst gekeken of @REG1 HL en @REG2 DE is. In dat -geval is EX DE,HL een kortere en snellere oplossing. -Natuurlijk moet ook worden gecontroleerd of @REG1 DE en -@REG2 HL is. -Is dat niet het geval dan worden de registerparen volgens de -bekende (ja toch?) manier verwisseld. - -Met dit macro is het verwisselen van twee registerparen een -koud kunstje en hoeft er niet meer worden gedacht aan EX -DE,HL. Alleen SP kun je niet gebruiken. Om nu 2 -registerparen te verwisselen hoef je alleen maar EXCH -reg1,reg2 in te geven en bovenstaand macro in je source -zetten. - - -## A B S O L U T E W A A R D E -``` - ABS MACRO - OR A - JP P,ABS@SYM - NEG - ABS@SYM: - ENDM -``` -Dit macro maakt A altijd positief. Als al A positief is dan -wordt er doorgeJumPt naar het einde van het macro (dat is -dan de instructie na het macro). - -@SYM wordt omgezet in een hexadecimaal getal van 4 cijfers. -Dit macro was anders niet te maken. Het zorgt er ook voor -dat de naam van het label verandert met de recursiediepte. -Ook was anders recursie in ��n macro zo goed als -onmogelijk... - - -## F A C U L T E I T -``` - FACT: MACRO @RESULT,@N - IF @N=1 - @RESULT DEFL 1 - ELSE - FACT T@SYM,@N-1 - @RESULT DEFL T@SYM*(@N) - ENDIF - ENDM -``` -Dit macro geeft een label een faculteit van een getal mee. -Helaas werkt het maar tot 6 faculteit. Het werkt vrij -ingewikkeld en je kunt beter gewoon 120 invullen in plaats -van dit macro te gebruiken, maar het is wel een mooi -voorbeeld. -``` - FACT: MACRO @RESULT,@N -``` -Dit definieert het macro FACT en de lokale variabelen -@RESULT en @N zijn de lokale variabelen. -``` - IF @N=1 - @RESULT: DEFL 1 -``` -Als er naar 1 faculteit gevraagd wordt geef dan gewoon ��n -terug. -``` - ELSE - FACT T@SYM,@N-1 -``` -Indien niet aan @N=1 voldaan wordt, wordt FACT nog eens -aangeroepen met als faculteit ��n minder en het label hangt -af van de recursiediepte (@SYM, zie boven). -``` - @RESULT: DEFL T@SYM*(@N) - ENDIF - ENDM -``` -Het label dat achter FACT bij het aanroepen staat krijgt de -waarde van de vorige variabele vermenigvuldigd met het -faculteitsgetal. - - -## B D O S -``` - BDOS: MACRO @FN1,@FN2 - IF "@FN2">"" - LD DE,@FCB - ENDC - LD C,@FN1 - CALL 5 - ENDM -``` -Dit macro maakt het aanroepen van de BDOS iets makkelijker: -``` - BDOS 9,Tekst -``` -is bijv. genoeg om de tekst achter het label Tekst op het -scherm te laten komen. -Maar mensen die MSX-DOS 2 gebruiken hebben eigenlijk niks -aan dit macro. MSX-DOS 2 heeft meestal wel meer dan ��n -input register(paar) nodig. - - -# V R A G E N , O P M E R K I N G E N ? - -Schrijf naar: - Stichting Sunrise - t.a.v. Kasper Souren - Postbus 2146 - 2400 CC Alphen aan den Rijn - -Of bel Sunrise BBS Nuth. - -Kasper Souren diff --git a/Sunrise Special/2/Memman 2.42.md b/Sunrise Special/2/Memman 2.42.md deleted file mode 100644 index a11728f..0000000 --- a/Sunrise Special/2/Memman 2.42.md +++ /dev/null @@ -1,76 +0,0 @@ -# M E M M A N 2 . 4 2 - - -In de speciale MemMan rubriek op de Special mag de nieuwste -versie van MemMan natuurlijk niet ontbreken. Eerst maar even -wat er allemaal nieuw is in deze nieuwe versie... - - -## W A T I S N I E U W ? - -1 - Voor mensen die de 32 kB RAM willen kunnen aansturen die - in BASIC achter de ROM's zitten, is er de functie GetTPA - toegevoegd. -2 - Voor HD-gebruikers wordt er een mogelijkheid geboden om - de TSR's makkelijker in te laden: in het environment - item TL dient de drive en de subdirectory te worden - opgegeven. Daarna kijkt TL niet alleen in de huidige - directory, maar ook de met TL aangegeven directory. -3 - Met TV.COM kun je nu ook zien in welk segment de diverse - TSR's zich bevinden. Zo kun je precies zoveel TSR's - wissen dat ��n segment vrijkomt. -4 - De stack van MemMan is nu in te stellen en/of uit te - lezen met de functies GetMMSP en SetMMSP. Tot nog toe - gebruikt alleen Tracer, die er al op voorbereid was, - deze mogelijkheid. -5 - In BASIC kun je nu een overzicht krijgen van de extra - commando's die de TSR's je verschaffen door CMD HELP in - te tikken. Tracer was (ook) hier op voorbereid. Maar ook - het ingebouwde MSX TsrUtils is er mee uitgerust. - Helaas moet de TSR dat wel zelf opvangen, het zou mooier - geweest zijn wanneer je, als programmeur, de gewenste - tekst in de TSR op een bepaalde plaats zet, zodat MemMan - CMD HELP afwerkt. -6 - TSR's kunnen MemMan nu aanroepen door naar #4002 te - springen; daar zit een MemMan entry. Hierdoor worden ze - sneller en kleiner. -7 - IniChk laat de functieafhandelingsroutine van MemMan nu - in HL achter. Daarna is een JP (HL) voldoende om naar - MemMan te springen. Maar TSR's hebben het, zoals in punt - 6 besproken, makkelijker. - - -## H O E K O M J E E R A A N ? - -Heel simpel te beantwoorden: Op deze disk staat MEMM242.PMA. -Deze library bevat alle 13 bestanden die bij MemMan 2.42 -behoren. O.a. een nieuwe versie van BK, de oude kon niet met -meer dan 4 MB overweg. - -Als je geen MSX-DOS 2 hebt, kopieer MEMM242.PMA en PMEXT.COM -dan naar een lege diskette (of een diskette met nog -voldoende ruimte) en typ het volgende in: - -PMEXT MEMM242 A: - -Als je MSX-DOS 2 hebt kan het veel sneller door de RAMdisk -te gebruiken. Maak een RAMdisk aan en doe vervolgens de -Special diskette in de drive. Typ nu het volgende in: - -PMEXT MEMM242 H: - -Na afloop natuurlijk wel nog even de files naar een diskette -kopi�ren. - - -## D A T U M E N T I J D - -Leuk aan MemMan is dat ze de datum en tijd van de files -aanpassen. Bij de meeste files is de tijd op 2:42 gezet, en -de datum op 19/09/92, de releasedatum van deze MemMan. - -Voor uitleg en technische specificaties bij MemMan verwijs -ik u naar de tekstfiles in MEMM242.PMA. - -Stefan Boer -Kasper Souren diff --git a/Sunrise Special/2/PCM Sampler.md b/Sunrise Special/2/PCM Sampler.md deleted file mode 100644 index 8133640..0000000 --- a/Sunrise Special/2/PCM Sampler.md +++ /dev/null @@ -1,760 +0,0 @@ -# P C M S A M P L E R - -Een van de leuke dingen van de turbo R is de ingebouwde PCM -sampler. Voor het opnemen en afspelen met deze PCM chip zijn -twee nieuwe BIOS calls aanwezig, die we in dit artikel -zullen gaan bespreken. - -Bovendien zal het programma LONG PCM worden besproken, -waarmee je zeer lange samples kunt opnemen en afspelen. De -lengte van deze samples is het RAM geheugen plus 32 kB, op -een standaard FS-A1ST is dit dus 288 kB en op een standaard -FS-A1GT 544 kB. Dit programma maakt gebruik van de BIOS -calls. - -De volgende keer zal ik uitleggen hoe je de PCM chip -rechtstreeks kunt aansturen. Hiervoor wordt onder andere de -systeem counter van de turbo R gebruikt, die dan ook zal -worden besproken. - -Maar nu eerst de twee nieuwe BIOS calls. - - -## N I E U W E B I O S C A L L S -``` -Naam: PCMPLY -Adres: &H0186 (MAIN ROM) -Functie: sample afspelen -Invoer: EHL = startadres - DBC = lengte - A = mode - bit 0 en 1: 00 15.75 kHz - 01 7.875 kHz - 10 5.25 kHz - 11 3.9375 kHz - bit 2-6: 0 - bit 7: 0 RAM - 1 VRAM -``` -Bij gebruik van alleen RAM zou een 16 bits adres voldoende -zijn, maar omdat we ook met VRAM kunnen werken zijn 17 bits -noodzakelijk. Daar wordt het DE register voor gebruikt, het -17de bit van het startadres staat in E en het 17de bit van -de lengte staat in D. Voor de duidelijkheid een paar -voorbeelden: - -1) Sample op adres &H9000-&HBFFF (RAM) afspelen op 5.25 kHz: -``` - LD HL,&H9000 - LD BC,&H3000 ; &HBFFF-&H9000+1 = &H3000 - LD DE,0 - LD A,&B00000010 - CALL PCMPLY -``` -2) Sample op adres &H04000-&H1BFFF (VRAM) afspelen op 15.75 - kHz: -``` - LD HL,&H4000 - LD BC,&H8000 ; &H1BFFF-&H04000+1 = &H18000 - LD DE,&H0100 - LD A,&B10000000 - CALL PCMPLY -``` -``` -Naam: PCMREC -Adres: &H0189 (MAIN ROM) -Functie: sample opnemen -Invoer: EHL = startadres - DBC = lengte - A = mode - bit 0 en 1: zie PCMPLY - bit 2 : 0 crunch mode uit - 1 crunch mode uit - bit 3-6 : trigger - bit 7 : zie PCMPLY -``` -Voor de uitleg bij EHL en DBC verwijs ik naar PCMPLY. Voor -bit 2 heb ik zelf maar de naam "crunch mode" verzonnen, ik -weet niet wat de offici�le naam hiervoor is. Als dit bit is -gezet neemt "stilte" veel minder geheugenruimte in beslag. -Een extra voordeel is dat je geen ruis hoort bij een -"stilte". Deze mode wordt bijvoorbeeld gebruikt bij zowel -het ingebouwde programma van de turbo R als bij de -meegeleverde sample tool. Je kunt duidelijk merken dat het -geheugen veel minder snel vol is als er weinig geluid is. - -De trigger kennen we al van de MSX-AUDIO sampler. Als PCMREC -wordt aangeroepen wordt gewacht met opnemen totdat er een -signaal binnenkomt dat de triggerwaarde evenaart. Als er 0 -wordt ingevuld voor de trigger wordt de opname meteen -gestart. Ook hier weer twee voorbeelden: - -1) Sample met 7.875 kHz opnemen van &H8300 tot &HD4FF (RAM), - trigger is uit en crunch mode is aan: -``` - LD HL,&H8300 - LD BC,&H5200 ; &H8300-&HD4FF+1 = &H5200 - LD DE,0 - LD A,&B00000101 - CALL PCMREC -``` -2) Sample met 3.9375 kHz opnemen van &H13000 tot &H13FFF - (VRAM), trigger is 10 en crunch mode is uit: -``` - LD HL,&H3000 - LD BC,&H1000 ; &H13000-&H13FFF+1 = &H1000 - LD DE,&H0001 - LD A,&B11010011 - CALL PCMREC -``` - -Het is nu tijd voor het voorbeeldprogramma: LONG PCM. Dit -programma is vanzelfsprekend ook onder dezelfde naam in het -softwaremenu te vinden en zoals u van mij gewend bent staat -de assemblerlisting in ASCII formaat op de disk onder de -naam "LONGPCM.ASC". We gaan deze source nu bespreken. - -(Ik denk dat het wel verstandig is om het programma eerst -eens uit te proberen, en dan pas de assemblerlisting te -bestuderen.) - -``` -; L O N G P C M . A S M -; Door Stefan Boer 25/10/92 -; Lange samples opnemen en afspelen -; Gebruikt 120 kB VRAM en RAM - 80 kB (voor DRAM en -; systeem RAM + routine) -; Alleen MSX turbo R -; Geen DOS2!! -``` - -Om het simpel te houden wordt DOS2 niet ondersteund, het -aansturen van het geheugen zou dan namelijk anders worden. -Bovendien moet er dan rekening worden gehouden met de 32 kB -RAM die DOS2 in beslag neemt, en dat doen we ook niet. - -``` -CHGMOD: EQU &H5F -ERAFNK: EQU &HCC -CHGET: EQU &H9F -CHPUT: EQU &HA2 -CHGCPU: EQU &H0180 -PCMREC: EQU &H0189 -PCMPLY: EQU &H0186 -LINL80: EQU &HF3AE -``` - -De in de routine gebruikte BIOS calls en systeem RAM -adressen worden hier gedefinieerd. - -``` - ORG &HC800 - IN A,(&HFE) - PUSH AF - LD A,&H82 - CALL CHGCPU ; R800 DRAM mode - CALL ERAFNK ; KEY OFF - LD A,80 - LD (LINL80),A ; WIDTH 80 - XOR A - CALL CHGMOD ; SCREEN 0 - DI - LD A,&HF1 ; COLOR 15,1,1 - OUT (&H99),A - LD A,7+128 - OUT (&H99),A - EI -``` - -Hier wordt eerst de inhoud van I/O poort &HFE bewaard, zodat -we die straks weer kunnen herstellen. Verder wordt de -computer in R800 DRAM mode gezet, en initialiseren we het -scherm. De R800 DRAM mode is noodzakelijk omdat anders -PCMREC alleen werkt bij lage frequenties. - -``` - CALL MEMCNT ; geheugen tellen - LD (MAXPGE),A -MAIN: LD HL,WELKOM - CALL PRINTS - LD A,(MAXPGE) - LD B,16 - DEFB &HED,&B11000001 ; MULUB A,B (HL=16*A) - LD BC,112 - ADD HL,BC ; VRAM erbij - CALL PRTDEC ; getal in decimaal naar scherm -``` - -Hier wordt eerste MEMCOUNT aangeroepen, mijn standaard- -routine om de grootte van de actuele memory mapper te -bepalen die we op Sunrise Special #1 al hebben behandeld. Ik -maak er hier dus verder geen woorden aan vuil. Deze routine -geeft in het A register de hoogste mapper pagina terug. Bij -256 kB is dit bijvoorbeeld 15. Deze waarde wordt opgeslagen. -Vervolgens worden de titel e.d. op het scherm gezet, de -routine PRINTS drukt een string af die op adres HL begint en -eindigt met een 0. - -Vervolgens wordt de hoeveelheid samplegeheugen berekend. -MEMCNT telt automatisch het RAM dat voor DRAM wordt gebruikt -al niet mee, op een turbo R met 256 kB is (MAXPGE) dus -gelijk aan 15-4 = 11. Er zijn dus 12 mapperpagina's, waarvan -er een (nr. 0) nodig is voor het systeem RAM en het -programma (die mapper pagina staat dus op &HC000). (MAXPGE) -geeft dus zonder verdere correctie het aantal memory mapper -pagina's (van 16 kB) dat voor samples vrij is. - -Dit vermenigvuldigen we via MULUB met 16, het antwoord komt -in HL. Vervolgens tellen we er nog 112 bij op, omdat we de -onderste 16 kB van het 128 kB grote VRAM niet gebruiken. -Deze waarde wordt met PRTDEC in decimaal naar het scherm -gestuurd (met voorloopnullen), deze standaardroutine zal ik -een andere keer nog wel eens bespreken. - -``` - LD HL,WELKM2 - CALL PRINTS - LD HL,MENU - CALL PRINTS -``` - -Met WELKM2 wordt er nog een "kB" achter het zojuist geprinte -getal gezet, achter MENU gaat het complete menu schuil. (Het -is misschien handig om even vooruit te kijken naar de -definites van WELKOM, WELKM2, MENU, etc.) - -``` - LD A,(FREQUE) ; current frequency - LD HL,FREQ0 - AND A - JR Z,FQ0 - LD HL,FREQ1 -FQ0: CALL PRINTS -``` - -Hier wordt de actuele frequentie (15.75 kHz of 7.875 kHz) op -het scherm gezet. Vanaf FREQ0 en FREQ1 staan de juiste -teksten, via een voorwaardelijke sprong wordt HL met de -juiste waarde geladen. Vervolgens wordt de juiste string -op het scherm gezet. - -``` - LD HL,MENU2 - CALL PRINTS - LD A,(CRUNCH) ; crunch mode - LD HL,CRU0 - AND A - JR Z,CR0 - LD HL,CRU1 -CR0: CALL PRINTS -``` - -Hier hetzelfde, alleen nu voor de crunch mode. - -``` - LD HL,MENU3 ; trigger - CALL PRINTS - LD A,(TRIGGR) - LD L,A - LD H,0 - CALL PRTDC2 -``` - -Bij de trigger gaat het om een getal. Dit wordt in HL gezet -en vervolgens wordt PRTDC2 aangeroepen, een ingekorte versie -van PRTDEC die een decimaal getal op twee cijfers print -(eventueel met voorloopnul). - -``` - LD HL,MENU4 - CALL PRINTS - LD A,(LIST_F) - OUT (&HA5),A ; listen aan/uit - LD HL,CRU0 - AND A - JR Z,LI0 - LD HL,CRU1 -LI0: CALL PRINTS ; listen -``` - -Tot slot van ons overzicht van de instellingen de instelling -"listen". Hiermee kan het binnenkomende signaal worden -beluisterd, handig om het volume af te stellen. Let op: zet -dit alleen aan als er een extrne geluidsbron (bv. CD speler) -of microfoon op de externe microfoonaansluiting op de -achterzijde is aangesloten, anders gaat het geluid zingen -wat een afschuwelijke herrie tot resultaat heeft! - -Het doorvoeren van het binnenkomende signaal naar de -luidspreker gaat met een OUT &HA5,10, u kunt dit ook in -BASIC gebruiken! Met een OUT &HA5,0 wordt het weer uitgezet. -De waarde wordt elke keer opnieuw naar I/O poort &HA5 -gestuurd, omdat het wordt uitgezet bij aanroep van PCMPLY of -PCMREC. - -``` - LD HL,PROMPT - CALL PRINTS -GETKEY: CALL CHGET - CP "1" - JR C,GETKEY - CP "7"+1 - JR NC,GETKEY ; controle tussen 1 en 7 - PUSH AF - CALL &HA2 - LD A,13 - CALL &HA2 - LD A,10 - CALL &HA2 -``` - -Hier wordt de prompt ("Your choice please?") op het scherm -gezet. Vervolgens wordt CHGET aangeroepen, die op een toets -wacht en de ASCII van die toets in A teruggeeft. We kijken -met voorwaardelijke sprongen of het een toets tussen 1 en 7 -is. De carry wordt bij CP "1" gezet als A kleiner is dan -&H31, de ASCII van "1". Bij een carry wordt het dus nog eens -geprobeerd. Bij de tweede CP wordt er vergeleken met "7"+1, -als A inderdaad kleiner of gelijk is aan 7 wordt de carry -niet gezet. Anders moeten we het nog eens proberen. Bij een -goede toets wordt AF bewaard en wordt er een linefeed -(13,10) gegeven. - -``` - POP AF - SUB "1" ; omzetten in getal 0-7 - ADD A,A - LD E,A - LD D,0 - LD HL,JPTAB - ADD HL,DE ; bereken adres in sprongtabel - LD E,(HL) - INC HL - LD D,(HL) - EX DE,HL - JP (HL) ; spring naar juiste routine -``` - -Hier wordt er aan de hand van het ingetoetse cijfer naar de -juiste routine gesprongen. Eerst halen we de eerder bewaarde -waarde van A terug met een POP. Vervolgens trekken we er de -ASCII van "1" vanaf, zodat we een getal tussen 0 en 6. Met -ADD A,A wordt dit met twee vermenigvuldigd, omdat een -sprongadres twee bytes in beslag neemt. Deze waarde wordt in -DE gezet en vervolgens bij het beginadres van de tabel met -sprongadressen (dat in HL staat) opgeteld. Het adres dat -hier staat wordt in DE gezet, en daarna met een EX DE,HL aan -HL overgedragen. De JP (HL) springt tenslotte naar het -juiste adres. Onthoud deze constructie goed, het is de beste -manier om een dergelijk menu te programmeren. - -Nu komen de afzonderlijke routines, die door het maken van -een keuze uit het menu worden aangeroepen. De routines -eindigen met een JP MAIN, waardoor het scherm wordt gewist -en het menu opnieuw opgebouwd. Vervolgens kan de gebruiker -zijn (of haar?) volgende keuze maken. - -``` -; 1) Record sample - -RECORD: LD HL,RECTXT - CALL PRINTS - CALL CHGET - LD HL,RECTX2 - CALL PRINTS -``` - -Eerst wordt er gevraagd om op een toets te drukken om met -het opnemen te beginnen. Vervolgens wordt de tekst -"Recording..." op het scherm gezet. - -``` - LD A,(TRIGGR) - ADD A,A - ADD A,A - ADD A,A ; * 8 ==> naar bit 3-6 - OR 128 ; VRAM - LD C,A - LD A,(FREQUE) - AND A - JR Z,CRNCH ; 15.75 kHz - SET 0,C ; 7.875 kHz -CRNCH: LD A,(CRUNCH) - AND A - JR Z,REC ; crunch mode uit - SET 2,C ; crunch mode aan -REC: LD A,C - PUSH AF -``` -Eerst samplen we het VRAM vol. Hier wordt de juiste waarde -voor het A register berekend. De trigger wordt met drie ADD -A,A instrukties naar bit 3-6 verplaatst. Met een OR 128 -wordt het VRAM bit gezet. Tot slot worden nog de juiste -crunch en frequntie bits toegevoegd. - -``` - LD HL,&H4000 ; startadres in VRAM = &H04000 - LD BC,&HC000 ; lengte in VRAM = &H1C000 - LD DE,&H0100 - CALL PCMREC -``` - -Het eigenlijke aanroepen van de BIOS routine wordt hier -gedaan. De eerste 16 kB VRAM wordt overgeslagen, hier staat -immmers de schermdata. - -``` - POP AF - AND &B00000111 ; wis VRAM en trigger - LD (PARAM),A -``` - -We hadden de berekende waarde voor A zojuist bewaard, zodat -we die niet nog een keer hoeven te berekenen. De trigger -moet nu echter worden uitgezet, omdat er anders een "gat" in -de opnamen komt bij de overgang van VRAM naar RAM. Uiteraard -wordt ook bit 7 (het VRAM bit) gewist. - -``` - LD A,(MAXPGE) - LD B,A -RECLUS: LD A,B - OUT (&HFE),A - PUSH BC - LD HL,&H8000 - LD BC,&H4000 - LD DE,0 - LD A,(PARAM) - CALL PCMREC - POP BC - DJNZ RECLUS - JP MAIN -``` - -Nu is het RAM aan de beurt. Bovenstaande lus wordt voor alle -mapper pagina's die beschikbaar zijn voor samplen doorlopen. -De juiste waarde wordt naar I/O poort &HFE gestuurd, -vervolgens wordt PCMREC met de juiste parameters -aangeroepen. - -``` -; 2) Play sample - -PLAY: LD HL,PLYTXT - CALL PRINTS - LD A,(FREQUE) - OR 128 ; VRAM - LD HL,&H4000 - LD BC,&HC000 - LD DE,&H0100 - CALL PCMPLY -``` - -Eerst worde tekst "Playing..." op het scherm gezet. -Vervolgens wordt de waarde voor het A register berekend. Bij -afspelen is dit veel simpeler dan bij opnemen, het gaat -immers alleen om de frequentie en het RAM/VRAM bit. -Vervolgens wordt de sample in het VRAM afgespeeld. - -``` - LD A,(MAXPGE) - LD B,A -PLYLUS: LD A,B - OUT (&HFE),A - PUSH BC - LD HL,&H8000 - LD BC,&H4000 - LD DE,0 - LD A,(FREQUE) - CALL PCMPLY - POP BC - DJNZ PLYLUS - JP MAIN -``` - -Deze lus lijkt sprekend op die voor het opnemen, verdere -uitleg is hier dan ook overbodig. Merk op dat het A register -nu alleen de frequentie bits bevat, het RAM/VRAM bit is -immers 0. - -``` -; 3) Frequency 15.75 kHz/7.875 kHz - -CHFREQ: LD A,(FREQUE) - XOR 1 - LD (FREQUE),A - JP MAIN -``` - -Hier wordt er geswitchd tussen 15.75 en 7.875 kHz. De -frequentie wordt aangegeven door bit 0 van (FREQUE), dit bit -wordt met een XOR 1 omgeklapt. Door de JP MAIN wordt de -wijziging vanzelf op het scherm zichtbaar gemaakt. - -``` -; 4) Crunch mode ON/OFF - -CHCRUN: LD A,(CRUNCH) - XOR 1 - LD (CRUNCH),A - JP MAIN -``` - -Analoog aan de frequentie. De trigger is echter wat -moeilijker, omdat hier een getal tussen 0 en 15 moet worden -ingesteld. We zetten daarom eerst een tekstje op het -scherm. Vervolgens wordt de tekst "Trigger: " op het scherm -gezet met daarachter de actuele waarde. Hiervoor gebruiken -we PRTDC2. - -``` -; 5) Change trigger - -CHTRIG: LD HL,TRGTXT - CALL PRINTS -CHTRG2: LD HL,TRGTX2 - CALL PRINTS - LD A,(TRIGGR) - LD L,A - LD H,0 - CALL PRTDC2 -CURSOR: CALL CHGET - CP " " ; spatie - JP Z,MAIN - CP 30 ; cursor omhoog - JR Z,TRGUP - CP 31 ; cursor omlaag - JR NZ,CURSOR - LD A,(TRIGGR) - AND A - JR Z,CURSOR - DEC A - LD (TRIGGR),A - JR CHTRG2 -``` - -Bij CURSOR wordt er op een toets gewacht. Is dit een spatie, -dan is de juiste waarde blijkbaar bereikt en kan worden -teruggekeerd naar het hoofdmenu. Voor cursor omhoog wordt -naar de juiste routine gesprongen. Is het ook niet cursor -omlaag, dan moet de gebruiker het nog maar eens met een -andere toets proberen (we springen terug naar cursor). -Cursor omlaag was nu dus ingedrukt, en dus controleren we -eerst met een AND A of A niet toevallig gelijk is aan 0, -want dan valt er niets te verlagen. Is dit niet het geval, -dan wordt A met een verlaagd en wordt de nieuwe trigger -waarde opgeslagen. Door naar CHTRG2 te springen wordt de -nieuwe waarde op het scherm gezet. - -``` -TRGUP: LD A,(TRIGGR) - CP 15 - JR Z,CURSOR - INC A - LD (TRIGGR),A - JR CHTRG2 -``` - -De routine voor trigger up is praktisch gelijk aan die voor -trigger down. Listen gaat weer net als frequentie en crunch, -met het verschil dat er hier wordt geswitchd tussen 10 en 0. -De OUT (&HA5),A is eigenlijk overbodig, dit wordt immers in -MAIN al gedaan. - -``` -; 6) Listen ON/OFF - -LISTEN: LD A,(LIST_F) - XOR 10 - LD (LIST_F),A - OUT (&HA5),A - JP MAIN - -; 7) Quit - -QUIT: LD HL,QUITTX - CALL PRINTS - POP AF - OUT (&HFE),A - RET -``` - -Bij het verlaten van het programma wordt er een -afscheidstekst op het scherm gezet. Vervolgens wordt de -inhoud van I/O poort &HFE hersteld en wordt er teruggekeerd -naar BASIC. - -``` -PRINTS: LD A,(HL) - AND A - RET Z - CALL CHPUT - INC HL - JR PRINTS -``` - -Deze standaardroutine zet een string op het scherm. HL wijst -naar het eerste teken van de string, de string moet zijn -afgesloten met een 0. Dit is een van de bekendste -standaardroutines. - -``` -MAXPGE: DS 1 -PARAM: DS 1 -FREQUE: DB 0 -TRIGGR: DB 0 -CRUNCH: DB 0 -LIST_F: DB 0 -JPTAB: DW RECORD,PLAY,CHFREQ,CHCRUN,CHTRIG,LISTEN,QUIT -``` - -Hierboven het numerieke datagebied. Hier worden de -variabelen opgeslagen, bovendien staat hier de sprongtabel -voor het menu. Hieronder volgt de tekstdata, alle strings -die in het programma met PRINTS op het scherm kunnen worden -gezet. (Nvdr. Omdat de layout van de Special in 60 kolommen -is, past het hier en daar niet echt lekker.) - -``` -WELKOM: DM 12,"LONG PCM v1.0 " - DM " By Stefan Boer 25/10/92" - ,13,10 - DM "MSX turbo R only, no MSX-DOS 2 allowed!" - ,13,10 - DM "Uses 112 kB VRAM and all your available RAM" - ,13,10,10 - DM "Total available memory: ",0 -WELKM2: DM " kB",13,10,13,10,0 -MENU: DM "1) Record sample",13,10 - DM "2) Play sample",13,10 - DM "3) Frequency 15.75 kHz/7.875 kHz",13,10 - DM "4) Crunch mode ON/OFF",13,10 - DM "5) Change trigger",13,10 - DM "6) Listen ON/OFF",13,10 - DM "7) Quit",13,10,10 - DM "Current frequency: ",0 -FREQ0: DM "15.75 kHz",13,10,0 -FREQ1: DM "7.875 kHz",13,10,0 -MENU2: DM "Crunch mode : O",0 -CRU0: DM "FF",13,10,0 -CRU1: DM "N",13,10,0 -MENU3: DM "Trigger : ",0 -MENU4: DM 13,10,"Listen : O",0 -PROMPT: DM 13,10,"Your choice please? ",0 -TRGTXT: DM 13,10,"Use cursor keys up and down, space bar - when ready",13,10,0 -TRGTX2: DM 13,"Trigger: ",0 -QUITTX: DM 13,10,"Good bye!",13,10,0 -RECTXT: DM 13,10,"Press any key to start recording",0 -RECTX2: DM 13,10,"Recording...",0 -PLYTXT: DM 13,10,"Playing...",0 -``` - -Onderstaande standaardroutine zet het getal in HL op het -scherm, met voorloopnullen. Deze routine wordt een andere -keer misschien nog eens behandeld. - -``` -; PRTDEC -; Zet getal in HL in decimaal op scherm -; Door Stefan Boer, juli 1992 - -PRTDEC: LD DE,1000 ; 0-9999 - CALL PRINT - LD DE,100 - CALL PRINT -PRTDC2: LD DE,10 ; 0-99 - CALL PRINT - LD DE,1 - CALL PRINT - RET - -PRINT: XOR A ; A=0 -NEXT: LD B,H - LD C,L ; LD BC,HL - OR A ; wis carry, A blijft gelijk - SBC HL,DE - JP C,EINDE - INC A - JP NEXT -EINDE: LD H,B - LD L,C ; LD HL,BC - ADD "0" - CALL CHPUT ; cijfer naar scherm - RET -``` - -De volgende standaardroutine is al op de vorige Sunrise -Special besproken, voor uitleg verwijs ik je dus naar die -Special. - -``` -; MEMCNT -; Door Stefan Boer 19/03/92 -; Uitvoer: A=aantal vrije memory mapper segmenten van 16 kB - -ADRES: EQU &H81FF -MEMPRT: EQU &HFE - -MEMCNT: LD HL,ADRES - LD DE,BUFFER - LD C,MEMPRT - IN A,(C) - PUSH AF - LD B,0 -SAVE: OUT (C),B - LD A,(HL) - LD (DE),A - INC DE - DJNZ SAVE - LD B,0 - XOR A -ZERO: OUT (C),B - LD (HL),A - DJNZ ZERO - LD D,0 - LD B,0 -CHECK: OUT (C),B - LD A,(HL) - CP &HFF - JR Z,SLAOVR - INC D - LD (HL),&HFF -SLAOVR: DJNZ CHECK - PUSH DE - LD DE,BUFFER - LD B,0 -RESTOR: OUT (C),B - LD A,(DE) - LD (HL),A - INC DE - DJNZ RESTOR - POP DE - POP AF - OUT (C),A - LD A,D - DEC A - RET - -BUFFER: DEFS 256 -``` - -## T O T S L O T - -In het softwaremenu vindt u het programmaatje LONGPCM.BAS, -dat de routine van disk laadt en start. Bovendien zorgt het -voor de terugkeer naar het softwaremenu. - -Ik wil er nog even op wijzen dat ik dit programma vooral heb -geschreven om de leerzaamheid, en niet om het nut. In de -routine komen behalve het samplen ook andere dingen voor, -zoals het maken van een menu. Het ging mij er uiteindelijk -om om te laten zien hoe de BIOS routines PCMREC en PCMPLY in -de praktijk kunnen worden gebruikt. - -De volgende keer zal ik zoals beloofd het direct aansturen -van de samplechip bespreken, de frequentie kan dan -bijvoorbeeld veel nauwkeuriger worden gekozen. Maar daarover -de volgende keer meer. - -Stefan Boer \ No newline at end of file diff --git a/Sunrise Special/2/PCM routines van de bios.md b/Sunrise Special/2/PCM routines van de bios.md deleted file mode 100644 index b5109a2..0000000 --- a/Sunrise Special/2/PCM routines van de bios.md +++ /dev/null @@ -1,84 +0,0 @@ -# P C M - R O U T I N E S V A N D E B I O S - - -Vertaling van een gedeelte van het artikel over de turbo R -uit het Japanse MSX-Magazine: - - -## P C M P L Y -``` -Funktie : PCM-weergave -Adres : Main ROM #0186 -In : A - Bit 7 6 5 4 3 2 1 0 - | | | | | `-`---> frequentie - | `-------------> 0 - `---------------> VRAM/MRAM - EHL (adres van de data) - DBC (lengte van de data) -Terug : carry flag - 0 normale beeindiging - 1 abnormale beeindiging - | - `--> A (reden van de abnormale beeindiging) - 1 fout bij het instellen van de frequentie - 2 onderbreking veroorzaakt door de STOP - toets - EHL (adres waar de onderbreking plaatsvond) -Verandert : alle registers -``` - -De PCM-geluidsdata worden als bit 7 van register A ��n is -uit het video-RAM gehaald en als het nul is uit het main RAM -gehaald. Bovendien hebben de waarden van het D- en -E-register slechts een betekenis in het geval dat de data -zich in het video-RAM bevindt. -D.m.v. bit 1 en bit 0 van de accumulator stelt men de -sample-frequentie in. Maar, pas op: 15.75 kilohertz is -alleen mogelijk wanneer de turbo R in de R800-DRAM-mode -staat: - -``` -00 W> 15.75 kilohertz -01 W> 7.875 kilohertz -10 W> 5.25 kilohertz -11 W> 3.9375 kilohertz -``` - -## P C M R E C -``` -Functie : PCM-opname -Adres : Main ROM #0189 -In : A - Bit 7 6 5 4 3 2 1 0 - | | | | | | `-`-> frequentie - | | | | | `-----> compressie - | `-`-`-`-------> trigger - `---------------> VRAM/MRAM - - EHL (adres van de data) - DBC (lengte van de data) -Terug : carry flag - 0 normale be�indiging - 1 abnormale be�indiging - | - `--> A (reden van de abnormale be�indiging) - 1 fout bij het instellen van de frequentie - 2 onderbreking veroorzaakt door de STOP - toets - EHL (adres waar de onderbreking plaatsvond) -Verandert : alle registers -``` -De codering van ingave bij bit 7, 1 en 0 van het A register -is hetzelfde als bij PCMPLY. Bit 6 t/m bit 3 van het A -register heten 'trigger' en duiden de sterkte van het geluid -aan, waarbij het zover komt dat de opname begint. Als deze -waarde nul is, wordt de opname onmiddellijk gestart. - -Verder worden, als bit 2 van register A ��n is, de -opname-data gecomprimeerd. Als het nul is, worden ze niet -gecomprimeerd. -Het comprimeren houdt in dat, als de input 0 is, het wordt -vervangen door een code. Dit kan heel veel bytes schelen. - -Bernard Lamers \ No newline at end of file diff --git a/Sunrise Special/2/Pauze toets.md b/Sunrise Special/2/Pauze toets.md deleted file mode 100644 index 7a71e8d..0000000 --- a/Sunrise Special/2/Pauze toets.md +++ /dev/null @@ -1,258 +0,0 @@ -# P A U Z E T O E T S - - -Zoals naar ik aanneem algemeen bekend is heeft de turbo R -een PAUSE toets, waarmee de computer kan worden stilgezet. -Deze PAUSE toets werkt softwarematig, en kan daardoor worden -omzeild. Dit in tegenstelling tot de PAUSE toets bij de Sony -MSX2+ computers, die hardwarematig werkt. Hierbij wordt de -computer ECHT stilgezet, waardoor er ook problemen optreden -bij externe geheugenuitbreidingen die dan geen refresh meer -krijgen. - -Deze problemen zijn er bij de turbo R niet, omdat de PAUSE -toets gewoon in de interrupt routine wordt uitgelezen. Voor -verdere uitleg over de interrupt routine verwijs ik u naar -de tekst over Interrupt Service Routines (ISR's) van Alex -van der Wal op deze Special. - - -## T U R B O R I S R - -Hieronder een disassembly van een deel van de ISR van de -turbo R. Ik zet hier alleen het deel dat voor de PAUSE toets -interessant is, voor de rest verwijs ik u dus naar de ISR -tekst van Alex. - -Bij elke interrupt springt de computer naar &H0038, waar een -JP naar de eigenlijke ISR staat: -``` -&H0038 C33C0C JP &H0C3C - -&H0C3C E5 PUSH HL -&H0C3D D5 PUSH DE -&H0C3E C5 PUSH BC -&H0C3F F5 PUSH AF -&H0C40 D9 EXX -&H0C41 08 EX AF,AF -&H0C42 E5 PUSH HL -&H0C43 D5 PUSH DE -&H0C44 C5 PUSH BC -&H0C45 F5 PUSH AF -&H0C46 FDE5 PUSH IY -&H0C48 DDE5 PUSH IX -&H0C4A CD9AFD CALL &HFD9A -&H0C4D C30B1A JP &H1A0B -&H0C50 F2020D JP P,&H0D02 -&H0C53 CD9FFD CALL &HFD9F -&H0C56 FB EI -``` -Zoals u ziet wordt er NA het aanroepen van &HFD9A naar een -routine gesprongen op adres &H1A0B: -``` -&H1A0B DB99 IN A,(&H99) ; S#0 lezen -&H1A0D A7 AND A ; vlaggen wissen -&H1A0E 08 EX AF,AF ; bewaren voor ISR -&H1A0F DBA7 IN A,(&HA7) ; PAUSE ingedrukt? -&H1A11 0F RRCA -&H1A12 3019 JR NC,&H1A2D ; nee, normale ISR -&H1A14 3AB1FC LD A,(&HFCB1) ; R800 en PAUSE led -&H1A17 F601 OR &H01 ; PAUSE led aan -&H1A19 D3A7 OUT (&HA7),A -&H1A1B 3E01 LD A,&H01 -&H1A1D D3A5 OUT (&HA5),A ; geluid uit -&H1A1F DBA7 IN A,(&HA7) ; wacht tot PAUSE -&H1A21 0F RRCA ; weer wordt -&H1A22 38FB JR C,&H1A1F ; ingedrukt -&H1A24 3AB1FC LD A,(&HFCB1) ; leds weer in -&H1A27 D3A7 OUT (&HA7),A ; oude stand -&H1A29 3E03 LD A,&H03 -&H1A2B D3A5 OUT (&HA5),A ; geluid aan -&H1A2D 08 EX AF,AF ; A=S#0 -&H1A2E C3500C JP &H0C50 ; verder met normale - ; ISR -``` -Het eerste gedeelte zit ook bij de MSX2 ISR, dit is gewoon -het uitlezen van S#0 om te kijken of het een 50/60 Hz -interrupt is of niet. De waarde van het A register wordt met -een EX AF,AF bewaard, zodat die straks weer aan de "normale -ISR" kan worden doorgegeven. - -Vervolgens wordt I/O poort &HA7 gelezen. Bit 0 van deze -poort geeft aan of PAUSE aan is of niet. Dit bit wordt gezet -zodra de PAUSE toets wordt ingedrukt, en blijft gezet totdat -de PAUSE toets nogmaals wordt ingedrukt. Is het bit 0, dan -is er geen PAUSE en wordt er verder gegaan met de normale -ISR. - -Is er wel PAUSE, dan wordt eerst het PAUSE led aangezet. Het -PAUSE led en het R800 led zitten ook op poort &HA7, en zoals -we zojuist al hebben gezien heeft poort &HA7 bij lezen een -andere functie, zodat de BIOS de status van de ledjes in het -systeem RAM bewaard (adres &HFCB1). Op de "oude" MSX -generaties met een datarecorder aansluiting was dit het -adres CASPRV, het werd gebruikt voor de datarecorder -routines. Aangezien de turbo R geen datarecorder aansluiting -meer heeft wordt dit adres nu voor dit nieuwe doel gebruikt. - -Enfin, &HFCB1 wordt gelezen en bit 0 wordt gezet (het PAUSE -led zit op bit 0, zie voor verdere uitleg over het aansturen -van de ledjes de speciale tekst daarover). Vervolgens wordt -het geluid uitgezet met een OUT (&HA5),1. Dit kun je normaal -ook gebruiken! - -Hierna wordt poort &HA7 constant uitgelezen, en gewacht -totdat de PAUSE toets weer wordt ingedrukt. Is dit gebeurt, -dan wordt eerst het led weer in de oude stand hersteld. Ik -zeg expres niet "uitgezet", omdat het PAUSE led blijft -branden als het al aanstond. Zoals u in de code kunt zien -wordt de waarde van &HFCB1 gewoon uitgelezen en naar poort -&HA7 gestuurd. - -Tot slot wordt het geluid aangezet en wordt er verder gegaan -met de normale ISR, u kunt de rest vinden in de ISR tekst. - - -## P A U S E U I T Z E T T E N - -De werking van de PAUSE toets kan op een zeer simpele manier -worden geblokkeerd: gewoon de interrupts uitzetten. Dit is -echter wel een zeer drastische oplossing, meestal heb je de -interrupts wel nodig en kan dit niet. - -Een andere methode wordt ook al in de ISR tekst aangedragen: -in de routine die je aan de hook &HFD9A hangt het -terugspringadres POPpen evenals alle registers die door de -ISR op de stack werden gezet. Ik verwijs hiervoor wederom -naar de ISR tekst. - -In machinetaal is dit een prima oplossing, in BASIC niet. -Alle dingen die normaal gesproken door de ISR worden gedaan -(toetsenbord uitlezen, ON SPRITE GOSUB, ON INTERVAL GOSUB, -ON KEY GOSUB, ON STRIG GOSUB) vinden nu niet meer plaats. -Dit geldt uiteraard ook voor de oplossing waarbij we de -interrupts helemaal uitzetten. - - -## D E O P L O S S I N G ? - -Er is nog een andere methode om dit probleem aan te pakken, -waarbij de rest van de ISR helemaal intact blijft. Het grote -nadeel is dat deze methode verre van standaard is. Ik heb de -routine op zowel FS-A1ST als FS-A1GT getest, maar het zou -heel goed kunnen dat het al niet meer werkt zodra er een -externe mapper wordt aangesloten. Het is zelfs vrijwel zeker -dat dit niet zal werken bij eventuele nieuwe MSX computers. - -Bij deze routine ga ik namelijk in de ISR in het ROM zitten -knoeien. In ROM knoeien kan toch niet, denkt u. Daar hebt u -gelijk in, maar zoals u weet heeft de turbo R de zgn. DRAM -mode, waarin RAM wordt gebruikt als ROM. In de tekst over de -R800 op Sunrise Special #1 heb ik al uitgelegd dat het -mogelijk is om bij wijze van spreken iets in de ROM te -veranderen door de ROM mode aan te schakelen, iets in het -RAM te veranderen dat voor DRAM wordt gebruikt, en -vervolgens weer de DRAM mode aan te schakelen. Deze methode -werkt dus alleen in samenwerking met de DRAM mode. - - -## I N D E I S R K N O E I E N - -We hoeven maar twee bytes in de ISR te veranderen om te -zorgen dat hij de PAUSE toets niet meer kan detecteren. Als -u nog even "terugbladert" kunt u zien dat er op adres &H1A0F -een IN A,(&HA7) instructie staat (opcode DB A7). We -veranderen dit gewoon in LD A,0 (opcode 3E 00), en de ISR -zal het niet meer merken als de PAUSE toets wordt ingedrukt. - -Dit wordt gedaan door "PAUSEOFF.BIN", een ML routine die op -deze diskette staat. De source staat er ook op, -"PAUSEOFF.ASC". Hier volgt deze source, voorzien van extra -commentaar. - -``` -; P A U S E O F F . A S C -; Alleen turbo R, zet PAUSE toets uit -; Door Stefan Boer, (c) Ectry 1992 -; Sunrise Special #2, (c) Sunrise 1992 - - ORG &HD000 - - LD A,&H81 - CALL &H0180 ; R800 ROM mode - IN A,(&HFE) - PUSH AF ; bewaar oude &HFE page - LD A,&HFC - OUT (&HFE),A ; DRAM page met MAIN ROM -``` - -Als de computer opstart worden de 32 kB MAIN ROM, de 16 kB -SUB ROM en de 16 kB Kanji ROM naar de bovenste 64 kB RAM -gekopieerd. Dit RAM wordt als DRAM gebruikt indien de R800 -DRAM mode wordt aangeschakeld. Hierbij komt de onderste 16 -kB van het MAIN ROM (waar wij in willen gaan knoeien) in -mapper page &HFC terecht. (Zie de R800 tekst op Sunrise -Special #1.) Wij zetten dit RAM op &H8000 met OUT -(&HFE),&HFC. - -``` - LD HL,(&H9A0F) ; &H1A0F+&H8000 - LD DE,&HA7DB ; DB A7 = IN A,(&HA7) - RST &H20 ; controle - JP NZ,ERROR ; foutmelding als niet Ok -``` - -Hier wordt gecontroleerd of op adres &H1A0F (dit wordt -&H9A0F omdat het op &H8000 staat) wel een IN A,(&HA7) staat. -Dit als een beperkte controle, op deze manier merk je het -bijvoorbeeld als het DRAM is gewist. - -``` - LD HL,&H3E ; 3E 00 = LD A,0 - LD (&H9A0F),HL ; knoeien - POP AF - OUT (&HFE),A ; &HFE page herstellen - LD A,&H82 - CALL &H0180 ; R800 DRAM mode - LD HL,TEKST - CALL PRTXT - RET -``` - -Hier wordt het "patchen" gedaan, en wordt de oude &HFE page -weer hersteld. Tot slot wordt de DRAM mode aangeschakeld en -melden we met een tekstje op het scherm dat de PAUSE toets -nu uit staat. - -``` -ERROR: LD HL,ERRTXT - CALL PRTXT - POP AF - OUT (&HFE),A - RET - -PRTXT: LD A,(HL) - AND A - RET Z - CALL &HA2 - INC HL - JP PRTXT - -TEKST: DM 13,10,"PAUSE inhibited",13,10 - DM "(c) Ectry 1992",13,10,10,0 - -ERRTXT: DB 13,10,7,"No correct DRAM found",13,10,0 -``` - -## T E N S L O T T E - -Nogmaals, dit is zeker geen standaardroutine! Maar hij zal -normaal gesproken wel werken en het voorkomt ongewenst -gebruik van de PAUSE toets, terwijl de ISR verder gewoon -zijn werk blijft doen. - -In machinetaal kun je veel beter de "POPjes aan &HFD9A -hangen" methode gebruiken, dat werkt altijd en kapt de (toch -onnodige) ISR af. - -Stefan Boer diff --git a/Sunrise Special/2/Programmeer taal c 2.md b/Sunrise Special/2/Programmeer taal c 2.md deleted file mode 100644 index c275e17..0000000 --- a/Sunrise Special/2/Programmeer taal c 2.md +++ /dev/null @@ -1,272 +0,0 @@ -# D E P R O G R A M M E E R T A A L C ( 2 ) - - - -## I N L E I D I N G - -In de vorige aflevering hebben we wat ge�xperimenteerd met -wat simpel rekenwerk in C. Deze aflevering gaan we eens wat -nader kijken naar het rekenen in C, want dat verschilt nogal -van PASCAL en BASIC. Vooral de filosofie erachter is nogal -anders. - -Zo kent C geen rekenkundige statements, alleen uitdrukkingen -(expressions)! Om van een uitdrukking een statement te maken -volstaat het er een ';' achter te zetten. Deze manier van -werken maakt het mogelijk allerlei onzinnige statements te -maken, die zonder problemen door de compiler verwerkt -worden. Kijk dus uit, want -``` - 1; -``` -is foutloos C, alleen gebeurt er weinig. - - -## R E K E N K U N D I G E U I T D R U K K I N G E N - -Een expression levert altijd een waarde op, maar als je er -een statement van maakt wordt er verder niets met die waarde -gedaan. De '=' (toewijzing, oftewel assignment) is ook een -operator, en geen (deel van) een statement. De waarde van -``` - x = 35 -``` -is gewoon 35, dus de uitdrukking die rechts van het '=' -teken staat. Dit heeft grote voordelen als je effici�nt en -compact wil programmeren. Zo maakt de uitdrukking -``` - y = (x = 35) + 2 -``` -x gelijk aan 35, en y gelijk aan 37, wat ook het resultaat -van de hele uitdrukking is. De haakjes zijn hier nodig, -omdat de '+'-operator een hogere prioriteit heeft dan de '=' -operator. de uitdrukking -``` - y = x = 2 + 35 -``` -zou zowel x als y gelijk maken aan 37. De prioriteiten van -de vele operators die C kent - en er zijn er ruim 40! - zijn -zelfs voor geoefende C-programmeurs nauwelijks uit het hoofd -te leren, vandaar dat het gebruik van haakjes, zelfs als dit -niet strikt nodig is, vaak is aan te raden. De gewone -rekenoperaties ('+' '-' '*' '/') hebben echter de prioriteit -die je ervan verwacht. - -Een grote bron van fouten is het verwisselen van de '=' en -de '==' operator. Laatstgenoemde is een vergelijkingoperator -(zie de vorige aflevering) die veel gebruikt wordt, maar -soms wordt er wel eens een enkele '=' getypt als er een -dubbele bedoeld wordt. Vergelijk eens de volgende lussen: -``` - do { /* hier allerlei statements */ } - while (x == 10); -``` -en -``` - do { /* hier allerlei statements */ } - while (x = 10); -``` -Je leest gemakkelijk over het verschil heen, maar de eerste -lus wordt be�indigd als x ongelijk aan 10 wordt, en in de -tweede lus wordt x altijd 10 gemaakt. Bovendien is de waarde -van de uitdrukking 'x = 10' gelijk aan 10 (niet nul, dus) en -wordt de lus nooit be�indigd! De compiler echter heeft geen -enkele moeite met deze twee lussen, en geeft ook geen -waarschuwing of foutmelding. De prijs van de flexibiliteit -van C is dus zorgvuldiger nakijken van het programma door de -programmeur. - - - -## D E A L G O R I T H M E V A N E U C L I D E S -``` -| | -| #include | -| | -| | -| /* Bepaal de grootste gemene deler van twee getallen */ | -| int ggd(grootste, kleinste) | -| int grootste, kleinste; | -| { | -| | -| int temp, rest; | -| | -| /* Zorg ervoor dat 'grootste' het grootste getal bevat */| -| /* Verwissel ze zonodig */| -| if (grootste < kleinste) { | -| temp = kleinste; kleinste = grootste; | -| grootste = temp; | -| } | -| | -| /* Het daadwerkelijke algorithme */ | -| | -| while (rest = (grootste % kleinste)) { | -| grootste = kleinste; | -| kleinste = rest; } | -| | -| return kleinste; | -| | -| } /* einde van functie ggd() */ | -| | -| | -| /* Hoofdprogramma */ | -| main() { | -| | -| int getal1, getal2; | -| | -| getal1 = 69; | -| getal2 = 253; | -| | -| printf("De grootste gemene deler van %d en %d is %d\n",| -| getal1, getal2, ggd(getal1, getal2)); | -| | -| printf("\nEinde programma\n\n"); | -| } | -| | -``` - -In dit programma worden heel wat nieuwe taalelemenen -ge�ntroduceerd: allereerst het gebruik van functies, het -if-statement, een iets andere versie van de reeds bekende -do..while lus, en het return-statement. - -Om te beginnen iets over functies, ofwel subroutines, in C. -In tegenstelling tot PASCAL kent C geen procedures. Dit is -geen groot gemis, aangezien we functies als procedures -kunnen gebruiken. De functiewaarde, die de functie geeft, -wordt dan eenvoudig niet gebruikt. - -Met de regels -``` - int ggd(grootste, kleinste) - int grootste, kleinste; -``` -geven we aan dat de definitie van de functie 'ggd' volgt. -(Voor functienamen gelden dezelfde regels als namen van -variabelen). Het 'int' voor 'ggd' laat de compiler weten dat -de waarde die de functie teruggeeft van het type 'int' is. - -De namen na het '(' zijn de parameters van de functie. Er -mag een willekeurig aantal parameters, door komma's -gescheiden, volgen (dus ook 0). In ons geval zijn dat er -twee, 'grootste' en 'kleinste'. - -In de volgende regel (of regels) worden de typen van de -parameters gespecificeerd. Dit gebeurt alsof het variabelen -zijn. Zo vreemd is dat niet, want binnen de functie (na de -'{') mogen de parameters precies als variabelen gebruikt -worden. In het bovenstaande geval hebben we dus twee -parameters van het type 'int'. - -Vervolgens worden er twee variabelen gedeclareerd van het -type 'int'. Net als in PASCAL zijn variabelen die binnen een -functie worden gedeclareerd - en daar rekenen we de -parameters van de functie ook onder - alleen binnen de -functie bekend. Dus 'grootste', 'kleinste', 'rest' en 'temp' -kunnen alleen binnen 'ggd' gebruikt worden, en zijn vanuit -'main' onbereikbaar. Wie denkt dit te kunnen omzeilen door -binnen 'main' deze variabelen opnieuw te declareren komt -bedrogen uit: de variabelen hebben weliswaar dezelfde naam, -maar zijn toch andere variabelen! - -Dit laatste betekent dat de C-programmeur zich geen zorgen -hoeft te maken of een bepaalde naam al binnen een andere -functie gebruikt wordt. Wil hij toch dat een bepaalde -variabele door verschillende functies gebruikt kan worden, -dan moet die variabele buiten een functie worden -gedeclareerd, d.w.z. aan het begin van het programma, of -tussen de functies in. - -De regels -``` - if (grootste < kleinste) { - temp = kleinste; kleinste = grootste; grootste = temp; } -``` -is een if-statement in C. Het lijkt veel op dat van BASIC of -PASCAL, alleen ontbreekt hier 'THEN'. Het 'THEN' is echter -impliciet! De algemene vorm van een if-statement is: - - if () - -Als een waarde oplevert die niet gelijk is aan -nul, dan wordt uitgevoerd. In het bovenstaande -voorbeeld moesten we dus weer een compound-statement -gebruiken. C kent ook een if..else statement: - - if () else - -Als een waarde oplevert die niet gelijk is aan -nul, dan wordt uitgevoerd, in het andere geval -. - -Wat de bedoeling is van het if-statement in het -voorbeeldprogramma staat al in de ervoor staande -commentaarregel! - -Nu krijgen we een nieuwe vorm van het while-statement, -namelijk: - - while () - -Dit werkt precies als het do..while statement, alleen wordt -er in het begin van de lus getest, en niet aan het eind. Dit -houdt tevens in dat niet wordt uitgevoerd, als - meteen al de waarde nul oplevert. Het programma -gaat dan verder na . In de do..while lus wordt - tenminste 1 keer uitgevoerd. - -De , zoals die in het voorbeeld wordt gebruik, -maakt al aardig gebruik van de mogelijk heden van C. Het '%' -in - - rest = (grootste % kleinste) - -betekent hetzelde als MOD in BASIC of PASCAL, de rest na -deling dus. Deze waarde wordt, heel toepasselijk, aan de -variabele 'rest' toegewezen, wat ook de uitkomst van deze -uitdrukking is. Als 'rest' dus nul wordt, wordt de lus niet -(meer) doorlopen. - -Na het compound statement na 'while' volgt een onbekend -statement, namelijk - - return kleinste; - -BASIC-programmeurs zullen nu de oren spitsen. Inderdaad -be�indigt een return statement een functie (subroutine). De -algemene vorm is: - - return; - -of - - return ; - -In het eerste geval wordt de functie be�indigd, zonder dat -er een functiewaarde wordt teruggegeven aan het programma -dat de functie aanriep, in het tweede geval gebeurt dat wel -(namelijk de waarde van ). In ons voorbeeld -wordt de inhoud van 'kleinste' gereturnd. Een kale 'return;' -aan het einde van een functie is overigens nooit nodig: de -compiler regelt dat zelf wel. - -De functie wordt nu afgesloten met een '}'. Het kan -eenvoudig bewezen worden dat deze functie inderdaad de -grootste gemene deler van twee getallen levert, maar dat -valt buiten het bestek van deze reeks. Een oefening voor de -lezer wellicht? Het is misschien interessant te weten dat -dit de oudst bekende algorithme ter wereld is. Zij dateert -van ruim voor het begin van onze jaartelling! - -Het hoofdprogramma - na 'main' - moet voor de trouwe lezer -weinig problemen opleveren. In 'printf' kun je zien hoe de -functie 'ggd' kan worden aangeroepen. Overigens mogen zelfs -een achter een functie met nul parameters de haakjes niet -worden weggelaten, dit in tegenstelling tot PASCAL. Doe je -dit toch dan krijg je bij de meeste compilers geen -foutmelding! (Voor de ge�nteresseerden: in plaats van de -functiewaarde krijg je dan de pointer naar de functie, -oftewel het adres van de functie. Over pointers wil ik het -echter pas in de volgende aflevering hebben). - -Robert Amesz \ No newline at end of file diff --git a/Sunrise Special/2/Programmeer taal c.md b/Sunrise Special/2/Programmeer taal c.md deleted file mode 100644 index b95b8f6..0000000 --- a/Sunrise Special/2/Programmeer taal c.md +++ /dev/null @@ -1,587 +0,0 @@ -# D E P R O G R A M M E E R T A A L C ( 1 ) - - - -## O V E R D E Z E C U R S U S - -Deze cursus is bedoeld voor MSX'ers die nader willen -kennismaken met de programmeertaal C. Enige -programmeerkennis in BASIC of PASCAL kan nuttig zijn, -aangezien de overeenkomsten en verschillen tussen C en de -andere twee talen uitgebreid aan bod zullen komen. Tevens -hoop ik dat het aantal C-programmeurs door dit initiatief -nogal zal stijgen, zodat een gezonde uitwisseling kan -ontstaan van ide�en, technieken, routines of zelfs hele -bibliotheken. - - -## D E C - C O M P I L E R S V O O R M S X - -Natuurlijk is het nuttig om een C-compiler te bezitten, om -de programmeervoorbeelden zelf te kunnen compileren. Bij -mijn weten zijn de volgende C-compilers voor MSX -beschikbaar: - -+ HiSoft C++ CP/M produkt, is echter in een voor MSX - aangepaste vorm beschikbaar. Geen PD, maar - toch ruim in BBS'en te downloaden. Overigens, - C++ is niet de C++ zoals het ANSI-comitee de - object-oriented versie van C gedoopt heeft. - Kent geen float's en long's. - -+ ASCII-C Speciaal voor MSX. Wat bewerkelijker in het - gebruik dan C++, maar levert zeer efficiente - code op, en stimuleert bovendien modulair - programmeren. Verder zeer flexibel. Kent geen - float's en long's. Ook geen PD, maar eveneens - goed verspreid onder de MSX'ers. Werkt - voortreffelijk samen met assembler. - -+ SMALL C CP/M produkt. Een Public Domain C, - oorspronkelijk gepubliceerd in Dr. Dobbs. Er - zijn vele varianten van in omloop. (Nvdr: - Natuurlijk omdat de source wordt - meegeleverd!) Levert helaas weinig efficiente - of compacte code, en kent in vergelijking met - de voorgaande twee compilers de meeste - beperkingen, met name de datastructuren zijn - zeer beperkt. Is daardoor niet echt geschikt - voor wat grotere programma's. - - GST-C Speciaal voor MSX. Lijkt van SMALL-C te zijn - afgeleid en kent ongeveer dezelfde - beperkingen. Geen PD. - - BDS-C CP/M produkt. Een wat oudere compiler, die - wel echter het volledigst de C-standaard - lijkt te volgen. Verder bij mij weinig van - bekend. - -Verder zijn andere C-compilers voor CP/M ook te gebruiken, -zoals AZTEC-C, MIX-C, enzovoort. - -De met een + gemerkte compilers heb ik zelf. Wellicht dat er -nog mensen zijn die een van de andere C-compilers in hun -bezit hebben, of compilers die zelfs niet in het lijstje -staan: in dat geval zou ik die graag eens ontvangen, om een -vergelijkend onderzoekje te doen. (Snelheid, grootte van -programma's, volledigheid). - - -## G E B R U I K V A N C - C O M P I L E R S - -C-compilers zijn wat omslachtiger in het gebruik dan BASIC, -of Turbo PASCAL (bij kleine programma's, tenminste). Om een -programma te compileren zijn de volgende stappen -noodzakelijk: - - + Editen van het ASCII-file met de programmatekst - (+ Pre-compileren) - + Compileren - (+ Assembleren) - (+ Optimaliseren) - (+ Linken) - -De stappen tussen haakjes zijn niet altijd noodzakelijk. -ASCII-C heeft vier van de vijf stappen nodig (alleen -optimaliseren niet), HiSoft C++ darentegen maar twee. De -meeste compilers zitten tussen deze twee uitersten in. - -Na de laatste stap hebben we als alles goed ging een -.COM-file gecre�erd, wat direkt onder MSX-DOS kan worden -uitgevoerd. Als het werkt: prima! Maar werkt het niet: "back -to the drawing-board". - - -## I N L E I D I N G - -In de loop der tijden hebben computerdeskundigen heel wat -manieren gevonden om computers te programmeren. De oudste en -primitiefste manier was programmeren in machinetaal door het -leggen van draadverbindingen! Onnodig te zeggen dat zoiets -alleen gaat bij de allerkleinste prorammaatjes. Ook uit die -tijd stamt de term "bug" (= fout in het programma), omdat -insekten toen daadwerkelijk voor sluitingen - en dus -veranderingen in het programma - in de grote panelen konden -zorgen. In die tijd was programmeren dan ook voorbehouden -aan de experts. - -Deze manier van programmeren moest gelukkig al snel het veld -ruimen voor wat geavanceerdere methodes: de assembler was -geboren, en programmeren werd al een heel stuk genoeglijker. -Toch bleven er problemen. In die tijd volgde het ene model -computer het andere snel op, en ieder nieuw model had weer -een wat andere machinetaal, en dus moesten de programma's -iedere keer door programmeurs vertaald worden. Duur en -omslachtig. - -Dus deden de eerste hogere programmeertalen hun intrede: -COBOL (COmmon Business Oriented Language), FORTRAN (FORmula -TRANslation) en ALGOL (ALGOrithmic Language). De laatste -twee zijn de stamvaders van de moderne programmeertalen. -BASIC (Beginners All-purpose Symbolic Instruction Code) is -duidelijk afgeleid van (een vroege vorm van) FORTRAN. BASIC -was in principe alleen bedoeld als oefentaal voor beginnende -programmeurs, en de ontwerpers ervan hebben dan ook geen -moeite gedaan om er structuur in aan te brengen, iets waar -ook de moderne BASIC's nog steeds last van hebben. - -ALGOL was de eerste programmeertaal die met enig beleid is -ontworpen. Een speciaal comitee, voornamelijk bestaand uit -wiskundigen, heeft begin zestiger jaren de defintie van deze -taal in een rapport vastgelegd. Uit deze taal is later -PASCAL voortgekomen. (PASCAL is gelukkig eens geen acroniem: -de naam komt van Blaise Pascal, een Frans wiskundige van een -paar eeuwen terug.) De syntax van PASCAL is bijna identiek -aan die van ALGOL, en is op sommige punten zelfs versimpeld -om het de compiler makkelijk te maken. Wel kent PASCAL meer -data-typen dan ALGOL. - -De taal C is in principe ook afgeleid van ALGOL, maar niet -direct. Ertussen zitten nog de talen BCPL en B, die speciaal -voor de relatief kleine computers in de PDP-serie bedoeld -waren. Ook C was in eerste instantie bedoeld voor -systeemprogrammatuur op een PDP-11 onder UNIX, en -instructies als "++" zijn in de taaldefinitie gekomen om -optimaal gebruik te maken van de instructieset van deze -processor. (Overigens, de instructieset van de "moderne" -68000 processor vertoont opmerkelijke overeenkomsten met die -van de PDP-11.) - -In C kun je heel abstract programmeren, maar ook heel -effici�nt en machinespecifiek. Dit maakt C zelfs in zijn -basisvorm een krachtige en prettige programmeertaal. Andere -talen - en met name Turbo PASCAL - moeten allerlei -niet-gestandaardiseerde uitbreidingen maken om die -flexibiliteit te benaderen. Evenaren is zelfs bijna -onmogelijk, zeker waar het het gebruik van pointers betreft. -Het nadeel is wel dat er hele obscure bug's kunnen ontstaan, -en dat is waarschijnlijk de reden dat er zo weinig MSX-ers -in C programmeren. - -Veel C-compilers staan ook toe om zelf bibliotheken te maken -met nieuwe functies, en die ook APART te compileren. In -ASCII-C is zelfs het grootste deel van de -standaardbibliotheek in C zelf geschreven. Dit alles maakt -het mogelijk om zgn. "modulair" te programmeren, wat wil -zeggen: een groot programma in kleinere deelprogramma's op -te splitsen en apart te programmeren. Dit houdt de -programmeerarbeid niet alleen overzichtelijk, maar het maakt -het ook gemakkelijk om meerdere mensen aan een programma te -laten werken door het werk eenvoudig te verdelen. - -De taal C is - net als PASCAL - een "kleine" -programmeertaal, wat inhoudt dat de taaldefinitie klein en -compact is gehouden. I/O valt in principe buiten deze -definitie, maar er zijn in de loop der tijden toch bepaalde -conventies en standaardbibliotheken ontstaan, waar we ons in -de cursus maar van zullen bedienen. Eveneens is C een zgn. -"free format" taal, wat inhoudt dat je de in de -programmatekst willekeurig spaties, tabs of crlf's -(newlines) mag gebruiken, mits er op die manier geen namen, -strings of symbolen in stukken worden gesneden. Dit in -tegenstelling tot bijvoorbeeld COBOL, waar voor ieder -programmaelement is vastgelegd op welke kolom die moet -beginnen. - -Ook in de cursus zal er aan de hand van voorbeelden de -verschillende taalelementen worden uitgelegd. Dus eerst een -voorbeeldprogramma, gevolgd door de uitleg. Tussendoor zal -wat dieper op bepaalde onderwerpen worden ingegaan. - -``` -| /* | -| De listings in de tekst staan tussen deze tekens. Ze | -| maken geen deel uit van het programma. Ze zijn alleen | -| bedoeld om duidelijk te maken waar de listings in de | -| tekst staan. Waar een enkel statement in de tekst wordt | -| besproken, zijn die dingen niet gebruikt, alleen | -| volledige programma's! | -| */ | -``` - -## M I J N E E R S T E C - P R O G R A M M A -``` -| | -| #include | -| | -| /* Mijn eerste programma */ | -| | -| main() { | -| | -| printf("Hello, world!\n"); | -| | -| } | -| | -``` -Dit is het equivalent van het BASIC-programma: -``` - 10 REM Mijn eerste programma - 20 PRINT "Hello, world" - 20 END -``` -Om een of andere reden wordt dit C-programma altijd gebruikt -voor de beginner, en met zo'n oude traditie wil ik niet -breken. - -De eerste regel -``` - #include -``` -is bedoeld om een aantal standaardfuncties, -definities en --constanten beschikbaar te maken voor de programmeur. In -feite betekent het alleen dat het file "STDIO.H" (staat voor -STandarD I/O) wordt opgenomen in het programma. Dit file kun -je ook gewoon bekijken met TYPE (onder DOS, natuurlijk). De -'<' en de '>' stellen een soort quotes voor, maar de gewone -'"' kan meestal ook. Met '#include "file"' kan overigens -iedere file in de programmatekst worden opgenomen, met -bijvoorbeeld eigen definities of constanten. Wel moet zo'n -'#include' helemaal aan het begin van een regel staan! (Dit -is dus een uitzondering op het bovengenoemde free-format). - -De volgende regel is een commentaarregel. De compiler -negeert alles tussen '/*' en '*/'. - -Vervolgens staat er -``` - main() { -``` -Dit is in feite een functiedefinitie, maar zonder -parameters, zodat er niets tussen de haakjes staat. In de -ruimte tussen ')' en '{' moeten de datatypes van de -parameters worden gegeven, dus die ruimte blijft ook leeg. -De naam 'main' is een bijzondere in C; het geeft aan dat dit -het hoofdprogramma (main program) is. Welke volgorde je je -functies ook hebben, de uitvoering van het programma begint -altijd bij 'main'. Na de '{' volgt de daadwerkelijke -functie, de zgn. 'body'. Hier bestaat die body uit een -statement, namelijk: -``` - printf("Hello, world!\n"); -``` -'printf' is een I/O functie, de naam staat voor "print -formatted", zoiets als PRINT USING in BASIC, maar je kan er -ook gewoon strings mee afdrukken. De '\n' aan het eind van -de string betekent dat er naar een nieuwe regel moet worden -gesprongen. De '\' (backslash) is een zgn. 'escape -character', wat aangeeft dat het volgende karakter een -bijzondere betekenis heeft. '\n' staat dus voor newline, -meestal een 'linefeed' met ASCII code 10, '\t' staat voor -tab, code 9, en zo zijn er nog een aantal. Met '\nnn', -waarbij nnn een OCTALE constante is kun je alle ASCII codes -van 0 tot 255 (0 tot 377 octaal, is dat) gebruiken, zelfs -als de editor daar moeite mee heeft! - -De ';' aan het eind van de regel geeft het eind van het -statement aan. Hoewel dit dus veel lijkt op PASCAL is er een -belangrijk verschil: in PASCAL scheidt de puntkomma twee -statements, en in C is het de afsluiting van een statement! -Als je daar niet op verdacht bent kan dat onverwachte -foutmeldingen opleveren! - -De '}' aan het eind van het programma geeft aan dat de -functie ten einde is. PASCAL-programmeurs kunnen -eenvoudigweg voor de '{' 'BEGIN' lezen en voor de '}' 'END' -om een en ander duidelijker te laten worden. - -Nu is het nog zaak om het programma te compileren en -eventueel te linken, en we hebben een programma dat -vriendelijk hallo zegt. Niet het meest spectaculaire -programma ter wereld, maar alle begin is eenvoudig. - - -## S I M P E L E D A T A T Y P E N I N C - -Net als BASIC en PASCAL kent C een aantal simpele datatypen, -die - net als PASCAL - als basis kunnen dienen voor -ingewikkelder datatypen. In deze paragraaf worden deze typen -besproken. Met deze datatypen kunnen we variabelen cre�ren. - -De basistypen zijn: - -TYPE GROOTTE BEREIK OMSCHRIJVING ------------------------------------------------------------- -char 1 byte 0..255 of -128..127 karakter -int 2 bytes -32768..32767 getal met teken -unsigned 2 bytes 0..65535 getal zonder teken -long 4 bytes -2147483648..2147483647 getal met teken -float 4 bytes +/- 1.0E+/-36 glijdende komma, 6 cijfers -double 8 bytes +/- 1.0E+/-36 glijdende komma, 13 cijfers - -De grootte en de precieze nauwkeurigheid van de 'float' en -de 'double' hangen nogal af van de implementatie, het zijn -dus slechts richtwaarden. Bovendien onbreekt er in de meeste -C-compilers voor MSX ieder spoor van floating-point typen, -waardoor e.e.a. nogal academisch is. Ook het 'long' type -ontbreekt meestal, wat eigenlijk veel lastiger is, omdat -sommige standaard bibliotheekfuncties daarmee zijn -gedefinieerd. - -De gegeven groottes en bereiken zijn overigens minima, maar -worden op 8-bitters, zoals onze Z-80 bij mijn weten nooit -overschreden. Het char-type moet overigens altijd 1 byte -groot zijn. De precieze grootte van elk datatype is altijd -op te vragen met de 'SIZEOF' pseudo-operator. Zo moet -'SIZEOF(char)' dus altijd de waarde 1 opleveren. (Het wordt -een pseudo-operator genoemd omdat er niets wordt uitgerekend -door het programma: de compiler vult er eenvoudigweg een -constante voor in). - -Sommige datatypen hebben ook pseudoniemen. Hier volgt een -lijstje: - - short int = int (op 8-bit computers, tenminste) - unsigned int = unsigned - long int = long - long float = double - - -## V A R I A B E L E N I N C - -Dat we nu de simpele data-types kennen in C is heel -plezierig, maar we moeten natuurlijk daar ook variabelen mee -kunnen declareren, d.w.z. cre�ren. Dit moeten we, net als in -PASCAL, zelf doen. BASIC cre�ert een nieuwe variabele op het -moment dat die voor het eerst gebruikt wordt. - -De naam van variabelen mag bestaan uit letters, cijfers en -'_', maar mag niet met een cijfer beginnen. Ook kan het zijn -dat de lengte van een naam beperkt is, maar dat hangt weer -van de compiler af. - -Het declareren van een variabele gaat als volgt: - - ; - -of: - - ,,.......; - -In het laatste geval worden er een aantal variabelen -gedeclareerd van hetzelfde type. De ';' aan het eind is -wederom verplicht! - -Voorbeelden: -``` - int x; - int y, z; - char lange_naam; - unsigned catch22; - float blub, blubblub; -``` - -## V O O R B E E L D P R O G R A M M A 2 E E N K W A D R A T E N T A B E L M A K E N - -In dit programma kan kennis worden gemaakt met wat simpel -gereken in C en het gebruik van variabelen. Ook komt de -eerste lus aan bod, de do..while lus. -``` -| | -| #include | -| | -| #define MAXWAARDE 10 | -| | -| /* Rekenen en de do..while lus */ | -| | -| main() { | -| | -| int waarde,kwadraat; | -| | -| waarde = 0; | -| | -| do { | -| kwadraat = waarde * waarde; | -| printf("Waarde = %4d Kwadraat = %4d\n", waarde, | -| kwadraat); | -| ++waarde; } | -| while (waarde <= MAXWAARDE); | -| | -| printf("\n\nThat's all folks!\n"); | -| } | -| | -``` -De '#include' kennen we nog van het vorige programma, maar -de '#define' is nieuw. Het is echter een simpele, doch -krachtige manier om de ene tekst door de andere te -vervangen. Iedere keer als de compiler dus het hele (!!) -woord 'MAXWAARDE' tegenkomt, wordt het door '10' vervangen. -De computer "ziet" dus: -``` - while (waarde <= 10); -``` -Maar 'MAXWAARDES' zou niet veranderd worden, omdat per heel -woord gekeken wordt. Hiervoor geldt hetzelfde als voor de -namen van variabelen: letters, cijfers en '_' mogen worden -gebruikt. De tekst, waarin dat woord wordt verandert hoeft -daar niet aan te voldoen. Met de regel -``` - #define ACCOLADE_OPEN { -``` -is dus niets verkeerds. - -Hoewel je woorden op die manier door willekeurige andere -tekst kunt vervangen, wordt het meestal alleen gebruikt om -constanten te definieren, zoals hierboven. Een van de -conventies in C is om zulke constanten altijd in -hoofdletters te schrijven, vanwege de duidelijkheid. Zulke -definities mogen ook weer binnen andere '#define's gebruikt -worden. Dus -``` - #define MAXKWADRAAT MAXWAARDE*MAXWAARDE -``` -is prima. - -Nadat we in 'main' zijn aangeland, worden de variabelen -'waarde' en 'kwadraat' gedeclareerd, beide van het int-type. -Vervolgens wordt met -``` - waarde = 0; -``` -de variabele 'waarde' nul gemaakt. In PASCAL zou ':=' -gebruikt worden in plaats van de '=', maar verder is alles -hetzelfde. - -Vervolgens gaan we de do..while lus binnen, maar daar heb ik -het later over. Dan staat er: - - kwadraat = waarde * waarde; - -De '*' betekent dus niets anders dan vermenigvuldiging, -tenminste als binaire operator. (Dat wil zeggen dat er twee -getallen nodig zijn bij een vermenigvuldiging, want 'bi' -betekent 'twee'.) Als unaire operator - 'un' is '1' --betekent dat sterretje iets heel anders, maar daarover een -andere keer. - -Hierna komt: -``` - printf("Waarde = %4d Kwadraat = %4d\n", waarde, kwadraat); -``` -wat ons leert hoe je met 'printf' ook getallen kunt -afdrukken. Hiervoor is in de string tweemaal het gedeelte -'%4d' opgenomen, om respectievelijk 'waarde' en 'kwadraat' -op het scherm te krijgen. Het procentteken geeft aan dat er -iets moet worden afgedrukt, de '4' geeft het aantal posities -aan waarin dat moet gebeuren, en de 'd' tenslotte geeft aan -dat het decimaal moet gebeuren. Er kan ook 'x' gebruikt -worden voor hexadecimale uitvoer, of 'u' als er een unsigned -moet worden afgedrukt. En dat is nog maar een klein deel van -alle mogelijkheden, maar voorlopig genoeg, lijkt me. Als -'waarde' 5 is en 'kwadraat' dus 25, komt er dit op het -scherm: - - Waarde = 5 Kwadraat = 25 - -gevolgd door een newline. Let goed op de lege ruimte voor de -getallen, doordat we een veldbreedte van 4 hebben opgegeven. -Als het getal te breed is voor het veld, wordt het getal -niet smaller gemaakt maar toch helemaal afgedrukt. Door als -veldbreedte dus '0' op te geven, of de veldbreedte weg te -laten (wat op hetzelfde neerkomt) wordt dus zo weinig -mogelijk ruimte gebruikt. - -De functie printf mag een variabel aantal parameters hebben, -maar de format-string is verplicht. Daaraan kan de functie -aflezen hoeveel parameters er nog volgen. Twee maal de '%4d' -in bovenstaand voorbeeld gaf dus aan dat er na de -format-string nog twee parameters volgden van het type -'int'. Een functie met een variabel aantal parameters wordt -een 'variadic function' genoemd. Een aantal compilers staan -toe zelf dit soort functies te schrijven, maar de preciese -details hoe je dat kan doen verschilt per compiler. - -Daarna staat er -``` - ++waarde; -``` -Dit is voor niet-C programmeurs onbegrijpelijk koeterwaals. -Het betekent echter alleen: tel 1 bij 'waarde' op. We hadden -dus ook kunnen schrijven: -``` - waarde = waarde + 1; -``` -De andere schrijfwijze is korter en sneller, wat in dit -voorbeeld misschien niet zo erg naar voren komt, maar in -iets ingewikkelder berekeningen wel. - - -Dan nu de do..while lus. Als algemene vorm heeft zij: - - do while (); - -Vertaald in het Nederlands: - - HERHAAL een statement ZOLANG (deze uitdrukking NIET nul is); - -Dan hebben we meteen een probleem, want we hebben niet een -enkel statement, maar drie! De oplossing is gelukkig -eenvoudig want als we een aantal statements achter elkaar -tussen '{' en '}' zetten, "ziet" C het als een enkel -statement. Dit wordt een 'compound statement' genoemd. - -Aan het einde van de lus staat: -``` - while (waarde <= MAXWAARDE); -``` -Lees voor '<=' 'kleiner of gelijk aan'. De '<=' is een -vergelijkingsoperator die 0 oplevert als de vergelijking -niet waar is, en een waarde ongelijk aan 0 als de -vergelijking klopt. - -Zolang 'waarde' in ons voorbeeld kleiner of gelijk is aan -10, klopt de vergelijking, en levert dus een waarde ongelijk -aan 0 op. Hierdoor wordt het programma weer vanaf het begin -van de lus doorlopen. Zodra 'waarde' groter dan 10 is -geworden, wordt niet meer naar het begin van de lus gegaan, -en vervolgt het programma gewoon. Hierdoor krijgen een -keurig lijstje met de getallen 0 t/m 10 en de kwadraten -daarvan. - -Na de boodschap - - That's all folks! - -stopt nu het programma. - -Nog even een lijstje met de vergelijkingsoperatoren die C -rijk is: - - > groter dan - >= groter dan, of gelijk aan - < kleiner dan - <= kleiner dan, of gelijk aan - == gelijk aan (jawel, twee is-gelijk tekens!) - != ongelijk aan - - - -Volgende keer meer. - -Vragen, opmerkingen of dreigbrieven aan: - - Stichting Sunrise - T.a.v. Robert Amesz - Postbus 2146 - 2400 CC Alphen a/d Rijn - -Of plaats een bericht in dit BBS (wel zo handig, nietwaar?): - - Future Base - Online ma-vr 22:00-06:00 za+zo 21:00-06:00 - Sysop: Johan Gijsman - Tel. 071-222380 - - -Een nuttig naslagwerkje over C dat voor plm. � 7,-- bij de -Slegte te koop is: - - F. Wagner-Dobler - "Zakboek C-language" - Delfia-Press, Rijswijk, 1987 - ISBN 90-6449-024-4 - -Dit is geen leerboek! Er staat echter bijzonder veel -informatie in. - -Robert Amesz \ No newline at end of file diff --git a/Sunrise Special/2/Rechtstreeks via PCM afspelen.md b/Sunrise Special/2/Rechtstreeks via PCM afspelen.md deleted file mode 100644 index a9710e3..0000000 --- a/Sunrise Special/2/Rechtstreeks via PCM afspelen.md +++ /dev/null @@ -1,123 +0,0 @@ -# R E C H T S T R E E K S V I A P C M A F S P E L E N - - -De PCM afspeelroutines in de turbo R zijn via een BIOS call -te gebruiken, maar kunnen dan maar op een beperkt aantal -snelheden ingesteld worden. De maximale sample-snelheid is -16 kHz. Dat is goed voor een redelijk geluid. PCM samples -voor de Amiga, PC (Soundblaster) en Apple Macintosh worden -echter regelmatig op snelheden van 22 tot 44 kHz opgenomen, -en klinken op een turbo R dan te langzaam als hiervoor de -BIOS wordt gebruikt. Sample-data rechtstreeks naar de PCM -sturen via de D/A-poorten biedt de oplossing. Het is ook -mogelijk samples met een hoge snelheid (dus hogere -kwaliteit) op te nemen door de BIOS te passeren, maar in -deze tekst beperk ik me tot het afspelen van samples. Ik heb -dit uitgezocht voor toepassing in het programma PLAYSMP, de -universele sample-speler voor iedere MSX2, MSX2+ en turbo R -(shareware t.g.v. Jos-Tel, staat ook op Sunrise Magazine -#6). - -Bij het afspelen van een sample via de BIOS doet de turbo R -het volgende: - -1. Kijk welke processor actief is - Is dit de Z80? - Dan bewaar het resultaat en schakel om naar R800-ROM -2. Reset de PCM (stel hem in op schrijven) -3. Voor TELLER=1 tot LENGTE (sample) - Lees een databyte - Stuur hem naar de PCM -LUS1: PCM klaar? - Als niet klaar, dan ga naar LUS1 -LUS2: Wachttijd verstreken (i.v.m. afspeelsnelheid)? - Als niet verstreken dan ga naar LUS2 - Verlaag TELLER, volgende byte -4. Reset de PCM -5. Was de oorspronkelijke processor Z80? - Dan schakel die weer in -6. Klaar - - -Om nu een hogere afspeelsnelheid te bereiken, kunnen we de -wachtlussen in de PCM routine simpelweg overslaan. Het is -ook niet noodzakelijk de processor om te schakelen, -aangezien een Z80A snel genoeg is voor samples van 44 kHz. -Wil je echter de zekerheid dat samples altijd op dezelfde -snelheid worden afgespeeld, dan moet je er wel voor zorgen -dat de processor altijd in dezelfde 'mode' staat. - - -## P R O G R A M M A - -Hieronder vind je een voorbeeld van een ML-subroutine waarin -een PCM sample op adres HL en met lengte BC wordt -afgespeeld. Het voorbeeld staat ook op disk onder de naam -PCMPLAY.ASC. - -``` -;SpeelPCM - -PCM: CALL RESPCM ;reset de PCM - CALL PLAY ;speel de sample af -RESPCM: DI - LD A,80H ;reset de PCM - OUT (0A4H),A - LD A,3 - OUT (0A5H),A - EI - RET ;klaar - -PLAY: LD A,(HL) ;pak byte op adres in HL - OUT (0A4H),A ;stuur naar PCM datapoort - INC HL ;verhoog pointer HL - DEC BC ;verlaag teller BC - LD A,B - OR C ;is BC al 0? - JR NZ,PLAY ;nee, volgende byte - RET ;ja, klaar -``` - -Bovenstaande afspeelroutine zal onder normale omstandigheden -veel te snel zijn, ook als de Z80 ingeschakeld is. Daarom -moet in de PLAY routine een vertragingslus worden ingebouwd: - -``` -WACHT: PUSH BC ;bewaar teller - LD B,WACHTTIJD ;wachten (0..255) -LUS: DJNZ LUS ;verlaag B, als niet 0 ga - ; naar LUS - POP BC ;herstel teller -``` - -Deze wachtlus is bijvoorbeeld in te bouwen tussen de INC HL -en DEC BC instructies. De BIOS van de turbo R bevat geen -wachtlus zoals hierboven aangegeven, maar bepaalt de -afspeelsnelheid aan de hand van terugmeldingen van de PCM, -wat een stuk nauwkeuriger is maar de al genoemde nadelen -heeft. Onderstaande routine is een stukje disassembly uit de -turbo R BIOS, dat thuishoort op de plaats waar hierboven -alleen de instructie OUT (0A4H),A staat: - -``` - OUT (0A4H),A ;stuur byte naar PCM -PAKPCM: IN (0A4H),A ;lees byte uit PCM - OR A ;nul? - JR Z,PAKPCM ;ja, wacht tot niet 0 - EXX ;alternatieve registers -PAKPC2: IN A,(0A4H) ;lees byte uit PCM - CP E ;gelijk aan E'? - JR NZ,PAKPC2 ;nee, herhaal - EXX ;terug naar normale - ; registers -``` - -Het moge duidelijk zijn dat de snelheid die de aanroepende -routine aan de BIOS-CALL PLAYPCM heeft doorgegeven inmiddels -in register E' is gezet (EXX; LD E,A; EXX). De turbo R scant -tijdens het afspelen van een sample ook nog de -toetsenbord-matrix om te kijken of de STOP-toets wordt -ingedrukt. Ik laat het aan de fantasie van de lezer over om -daar zelf een routine voor te schrijven. - -Pierre Gielen \ No newline at end of file diff --git a/Sunrise Special/2/Stereo SCC.md b/Sunrise Special/2/Stereo SCC.md deleted file mode 100644 index 994c42b..0000000 --- a/Sunrise Special/2/Stereo SCC.md +++ /dev/null @@ -1,20 +0,0 @@ -# S T E R E O S C C - -Het idee van het ombouwen van de SCC naar een zogenaamde -stereo SCC is niet nieuw. Maar omdat ik nog nooit ergens een -tekst hierover ben tegengekomen, heb ik deze tekst maar even -geschreven. Voor de knutselaar is het een leuk projectje! - -Waarschuwing: Het uitvoeren van deze ingreep in uw SCC is op -eigen risiko, gaat er iets mis dan vervalt uw garantie. -Sunrise is op geen enkele manier aansprakelijk voor enige -schade die uit dit project kan voortvloeien! - -Het ombouwen is eigenlijk gigantisch simpel, maar desondanks -heb ik de volledige beschrijving maar even als DP file op -deze schijf gezet. Laad deze in met Dynamic Publisher (naam -van de file: STEREOSC.PCT). - -Veel plezier met de "stereo SCC" en tot een volgende keer! - -Haiko de Boer \ No newline at end of file diff --git a/Sunrise Special/2/VDP Cursus 1.md b/Sunrise Special/2/VDP Cursus 1.md deleted file mode 100644 index 487713f..0000000 --- a/Sunrise Special/2/VDP Cursus 1.md +++ /dev/null @@ -1,418 +0,0 @@ -# M S X 2 / 2 + V D P C U R S U S ( 1 ) - - - -## H E R H A L I N G - -Deze cursus is al eerder verschenen op de ClubGuide en -Sunrise Magazine, vanaf ClubGuide #7. Omdat ik tientallen -brieven van lezers heb gekregen die de eerste delen hebben -gemist, heb ik besloten om de cursus opnieuw te publiceren, -nu op de Sunrise Special. - -Een andere reden om de cursus opnieuw te publiceren is dat -ik intussen meer weet over de VDP, zodat ik de cursus nog -beter kan maken. De tekst zal ik grotendeels herschrijven, -de oude cursus dient eigenlijk vooral als basismateriaal. Ik -zal vooral meer aandacht besteden aan het programmeren van -de VDP in ML. Hierdoor is de VDP cursus op herhaling ook -interessant voor de lezers die de cursus al vanaf deel 1 -hebben gevolgd. Veel plezier met de VDP cursus op herhaling! - - -## I N L E I D I N G - -Je kunt veel meer uit de VDP halen door hem rechtstreeks aan -te sturen. Zelfs in BASIC zijn er al aanmerkelijke -snelheidsverbeteringen mee te realiseren. Alle schitterende -VDP truuks die u in de demo's op de Sunrise Picturedisk kunt -bewonderen worden bereikt door het rechtstreeks aansturen -van de VDP. Het moet in principe mogelijk zijn dat u aan het -eind van de cursus ook dergelijke truuks met de VDP kunt -uithalen, mits er natuurlijk voldoende kennis van ML -aanwezig is. - -Dit artikel is zowel voor MSX2 als voor MSX2+-gebruikers -bestemd. De V9938 (MSX2) en de V9958 (MSX2+) zijn namelijk -grotendeels hetzelfde. Alleen waar er verschillen zijn, zal -het artikel opsplitsen in een MSX2 en een MSX2+ deel. De -informatie in dit artikel is zeer betrouwbaar, want het -meeste komt rechtstreeks uit de Technical Data Books van -Yamaha. (Inmiddels is er ook de turbo R, die echter dezelfde -VDP bezit als de MSX2+.) - - -## L E Z E N E N S C H R I J V E N V A N V D P - R E G I S T E R S - -Voordat we iets met de VDP kunnen doen is het eerst -noodzakelijk om te weten hoe de VDP kan worden aangestuurd. -Het aansturen van de VDP registers kan op drie manieren, -namelijk in BASIC met het VDP commando, in machinetaal met -BIOS calls en in machinetaal door rechtstreeks I/O poorten -te lezen/schrijven. Ik zal deze methodes nu ��n voor ��n -bespreken. - - -## B A S I C - -In BASIC kun je VDP-registers uitlezen of beschrijven met -het VDP(N) commando. Voor N moet je meestal NIET het regis- -ter nummer invullen, zoals die verder in dit artikel worden -gebruikt. Een register wordt aangegeven met R#nummer -(bijvoorbeeld R#23) en een statusregister met S#nummer. In -BASIC moet je de volgende omrekentabel gebruiken: -``` -Register: N: Lezen/Schrijven: ------------------------------------------------------------- -R#00-R#07 0- 7 L/S -R#08-R#23 9-24 L/S -R#25-R#27 26-28 (alleen 2+) L/S -R#32-R#46 33-47 L/S -S#00 8 L -S#01-S#09 -1 - -9 L ------------------------------------------------------------- -``` -Schrijven doe je met VDP(N)=waarde en lezen met W=VDP(N). -Bijvoorbeeld VDP(10)=0 of PRINT VDP(1). - - -## M A C H I N E T A A L - -In machinetaal kun je voor het lezen/schrijven van VDP -registers de routines gebruiken die al in het ROM van je -MSXje zitten. Dat zijn: - -&H0047 WRTVDP Schrijft naar VDP-register. - Invoer: C = register, B = data - Verandert: AF,BC -&H013E RDVDP Lezen van S#0 van VDP. - Uitvoer: A = data -&H012D EXT WRTVDP Schrijft naar VDP-register. - Invoer: C = register, B = data - Verandert: AF,BC - -(EXT betekent dat de routine in het Extended ROM staat. Je -moet zo'n routine aanroepen door het adres in IX te laden en -daarna CALL &H015F te geven.) - -&H0131 EXT VDPSTA Lezen van statusregister van VDP. - Invoer: A = register (0-9) - Uitvoer: A = data - Wijzigt: F - -Het lezen van niet-statusregisters is niet mogelijk. Wel -wordt er door de BIOS routines een tabel bijgehouden van de -VDP registers in het systeem RAM. Deze tabel is alleen -betrouwbaar als de VDP registers alleen via de BIOS routines -worden beschreven, of als u er zelf voor zorgt dat u bij het -schrijven van een register de waarde in het RAM bijwerkt. -Dit verbetert vaak de samenwerking met andere programma's -(bijvoorbeeld MemMan TSR's). - -De inhoud van de VDP registers wordt door het BIOS op de -volgende plaatsen in het systeem RAM bijgehouden: - -R#0-R#7 &HF3DF-&HF3E6 -R#8-R#23 &HFFE7-&HFFF6 -R#25-R#27 &HFFFA-&HFFFC - -De commandoregisters R#32-R#46 worden niet (of in ieder -geval niet op deze manier) in het systeem RAM opgeslagen. -Dit is in principe ook onzin, omdat deze registers na het -uitvoeren van het commando hun oorsponkelijke waarde hebben -verloren. (N.B. Bij gebruik van de VDP door de SUB ROM -routines voor COPY e.d. worden de commando registers -uiteraard wel in het systeem RAM gezet, maar dit is voor ons -verder niet interessant.) - - -## V I A I / O P O O R T E N - -1) Direct - -Schrijf eerst de data en daarna het registernummer naar port -#1, waarbij bit 7 is gezet. Officieel moet de I/O poort uit -het ROM worden gelezen, maar onderstaande waardes gelden -altijd, en mogen dus gewoon gebruikt worden: - -port #0 I/O &H98 -port #1 I/O &H99 -port #2 I/O &H9A -port #3 I/O &H9B - -Het gaat dus volgens het volgende schema: (binair) - - MSB 7 6 5 4 3 2 1 0 LSB -Port #1 First Byte D7 D6 D5 D4 D3 D2 D1 D0 DATA - Second Byte 1 0 R5 R4 R3 R2 R1 R0 REGISTER # - - -In machinetaal ziet dit er zo uit: -``` - DI - LD A,100 - OUT (&H99),A - LD A,23+128 - OUT (&H99),A - EI -``` -Hier wordt de waarde 100 naar R#23 geschreven. Door 128 bij -het registernummer op te tellen wordt bit 7 gezet, waarmee -we de VDP vertellen dat hij het getal dat hij daarvoor had -ontvangen naar een register moet schrijven, waarvan het -nummer in de onderste zes bits staat. - -De interrupts moeten hierbij altijd uitstaan, omdat er -anders tussen de OUTs een interrupt kan optreden, waardoor -het misgaat omdat er in de interrupt meestal wel iets met de -VDP wordt gedaan. Als de interrupts al uit stonden kunt u de -DI en EI natuurlijk weglaten, de EI kan natuurlijk worden -weggelaten als de interrupts uit moeten blijven staan -(bijvoorbeeld omdat er nog een VDP register wordt -beschreven). - -Je zou dit natuurlijk ook in een subroutine kunnen zetten, -maar dat heeft weinig nut omdat het zo veel sneller gaat. - - -2) Indirect - -Zet eerst het registernummer in R#17, dat kan niet op de -indirekte manier. Schrijf daarna de data naar port #3. Dit -is vooral erg handig als je een reeks opeenlopende registers -wilt beschrijven (bijvoorbeeld de commando registers R#32 -t/m R#46). Als je namelijk AII (bit 7 van R#17, Auto -Increment Inhibit) op 0 zet, wordt R#17 automatisch -verhoogd. In schema gaat het als volgt: -``` - MSB 7 6 5 4 3 2 1 0 LSB -R#17 AII 0 R5 R4 R3 R2 R1 R0 REGISTER # -Port #3 First Byte D7 D6 D5 D4 D3 D2 D1 D0 DATA -Port #3 Second Byte D7 D6 D5 D4 D3 D2 D1 D0 DATA -... -Port #3 nth Byte D7 D6 D5 D4 D3 D2 D1 D0 DATA -``` - -Dit wordt vooral veel gebruikt bij het sturen van commando's -naar de VDP. De commandoregisters worden pas in deel 3 en 4 -behandeld, maar ik zal nu vast een stukje standaarcode -geven. We maken hier gebruik van de instructie OTIR van de -Z80, dat B bytes vanaf adres HL naar poort C stuurt. Stel we -willen de 15 waardes die achter COPY: staan naar de -commandoregisters sturen (R#32 t/m R#46): -``` - DI - LD A,32 - OUT (&H99),A - LD A,17+128 - OUT (&H99),A -``` -Hiermee zetten we het "beginregister" voor het indirect naar -de VDP schrijven op 32, omdat het AII bit gelijk is aan 0 -wordt dit registernummer automatisch verhoogd als we een -byte naar Port #3 schrijven. -``` - LD B,15 - LD C,&H9B ; LD BC,&H0F9B kan ook - LD HL,COPY - OTIR - . - . - . -COPY: DB 0,1,0,1,0,2,1,2,3,4,1,2,1,2,3 ; willekeurige data -``` - -Zoals we al eerder hebben gezien is het adres van Port #3 -gelijk aan &H9B. Met de OTIR sturen we de 15 waardes naar -register 32 t/m 46. - - -3) Palette Registers - -Voor het palet heeft de VDP paletteregisters P#0 t/m P#15, -die alleen indrect aan te sturen zijn. Het paletnummer moet -in R#16 staan, dit wordt automatisch verhoogd nadat het -paletregister is beschreven. Voor elk paletregister zijn -twee bytes nodig, waarvan slechts 9 bits worden gebruikt. 3 -voor rood, 3 voor blauw en 3 voor groen. Totaal geeft dat -2^9=512 kleuren. De databytes moeten naar Port #2 worden -geschreven. Wederom een schema: - -``` - MSB 7 6 5 4 3 2 1 0 LSB -R#16 0 0 0 0 C3 C2 C1 C0 paletnummer -Port #2 First Byte 0 R2 R1 R0 0 B2 B1 B0 data - ROOD BLAUW -Port #2 Second Byte 0 0 0 0 0 G2 G1 G0 data - GROEN -``` - -De waarde in R#16 wordt automatisch verhoogd, als je het -hele palet wilt invullen hoef je dus slechts eenmaal de -waarde 0 naar R#16 te schrijven en kun je daarna 32 bytes -naar Port #2 schrijven. De volgende standaardroutine -schrijft een willekeurig palet naar de VDP: -``` - DI - XOR A - OUT (&H99),A - LD A,16+128 - OUT (&H99),A ; P#0 selecteren - LD BC,&H209A ; 32 bytes naar &H9A - LD HL,PALET ; palet staat vanaf PALET - OTIR ; stuur palet uit -``` - -## S T A T U S R E G I S T E R S L E Z E N - -Als je de statusregisters van de VDP (S#0-S#9) wilt lezen -moet je eerst het registernummer in R#15 zetten. Vervolgens -moet je port #1 uitlezen. Hier het schema: -``` - MSB 7 6 5 4 3 2 1 0 LSB -R#15 0 0 0 0 S3 S2 S1 S0 STATREG # -Port #1 Read data D7 D6 D5 D4 D3 D2 D1 D0 DATA -``` -Omdat de interrupt routine in het BIOS zo snel mogelijk te -houden wordt er vanuit gegaan dat statusregister 0 altijd -geselecteerd is, er wordt dus simpelweg IN A,(&H99) gedaan -om S#0 te lezen (dit is nodig om te kijken of een interrupt -van de VDP afkomstig is on niet). De interrupts moeten -daarom bij het uitlezen van een statusregister altijd uit -staan, en S#0 moet weer geselecteerd zijn als de interrupts -weer aan worden gezet. In onderstaand voorbeeld wordt S#2 -uitgelezen in ML: -``` - DI - LD A,2 - OUT (&H99),A - LD A,15+128 - OUT (&H99),A ; S#2 selecteren - NOP - NOP ; wacht even - IN A,(&H99) - EX AF,AF - XOR A - OUT (&H99),A - LD A,15+128 - OUT (&H99),A ; selecteer S#0 voor BIOS - EI - EX AF,AF ; waarde S#2 staat nu in A -`` - -De twee NOPs zijn nodig om de VDP de tijd te geven om de -data klaar te zetten op Port #1. Er wordt twee keer EX AF,AF -gebruikt, zodat de waarde van het statusregister aan het -einde van het stukje code nog in A staat. - -Eventueel kan IN A,(&H99) als volgt worden vervangen om te -wachten totdat een bepaald bit (in het voorbeeld bit 0) van -het statusregister 0 is: -``` -WAIT: IN A,(&H99) - BIT 0,A - JP NZ,WAIT -``` -In dit geval is het natuurlijk niet nodig om het A register -te bewaren met EX AF,AF, eventueel kan een bepaalde actie -die moet worden uitgevoerd zodra het bit 0 is eerst worden -uitgevoerd, dus voordat S#0 weer wordt geselecteerd. Als de -interrupts maar uit staan! - - -## A A N S T U U R S N E L H E I D - -Hoewel dit nergens in het MSX2 Technical Handbook van ASCII -staat, kunnen er problemen ontstaan als de VDP te snel wordt -aangestuurd. Dit is afhankelijk van de afstand tussen de -processor en de VDP in de computer. Onderstaande manier van -de VDP aansturen is dan ook af te raden, omdat dit niet op -alle computers goed zal werken: -``` - DI - LD C,&H99 - LD D,0 - LD E,128+9 - OUT (C),D - OUT (C),E -``` -De OUTs worden hier te snel achter elkaar gegeven. -Vuistregel is om ongeveer zeven Z80-klokpulsen tussen twee -OUTs te wachten. Dit komt overeen met twee NOPjes of -bijvoorbeeld een LD A,x instructie. In bovenstaand -voorbeeld wordt de waarde 0 naar R#9 geschreven. Dit kan -beter als volgt gebeuren, zodat het op alle computers werkt: -``` - DI - XOR A - OUT (&H99),A - LD A,128+9 - OUT (&H99),A -``` -Extra voordelen hiervan zijn dat je veel minder registers -gebruikt, en dat het nog sneller is ook! Zorg er dus voor -dat bij het schrijven naar Port #0 t/m Port #3 altijd even -wordt gewacht tussen twee OUTs! De "snelheidswinst" die door -twee OUTs achter elkaar wordt gehaald is echt te -verwaarlozen, en bovendien geeft dit "troep op het beeld" -bij sommige computers! - - -## R 8 0 0 - -Nu verwacht u misschien problemen bij de turbo R, bij de -R800 duurt een LD A,x of twee NOPjes immers veel korter dan -bij de Z80. Maar dan onderschat u de mensen bij ASCII, die -natuurlijk rekening hebben gehouden met dit probleem. In de -R800 stand zorgt de S1990 er namelijk voor dat de R800 bij -elke OUT naar de VDP een bepaalde tijd moet wachten, die -overeen komt met de offici�le aanstuursnelheid van de VDP -zoals die door Yamaha wordt opgegeven. Het enige nadeel -hiervan is dat deze tijd iets langer is dan per se nodig. -Gelukkig is de R800 zo snel dat je daar verder weinig van -merkt. Het maakt in R800 stand dus niet uit hoe snel de data -naar de VDP wordt gestuurd, maar omdat de R800 toch moet -wachten heeft het weinig zin om de "twee OUTs direct achter -elkaar methode" toe te passen. - -Het is overigens niet zo (zoals in het begin van het turbo R -tijdperk werd beweerd) dat de VDP sneller is op de turbo R. -Hij is gewoon precies even snel. Het aansturen van de VDP -met OUTs gaat in R800 mode zelfs iets langzamer! VDP -routines (bij bijvoorbeeld Micro Cabin spellen zoals Xak -III) worden wel sneller op de R800, maar dat komt omdat het -rekenwerk dat aan vrijwel iedere VDP opdracht vooraf gaat -natuurlijk een stuk sneller gaat bij de R800. - - -## T E N S L O T T E - -Ik hoop dat ik veel trouwe lezers een plezier heb gedaan met -deze herhaling. Vooral in deze aflevering heb ik veel -veranderd, in de oorspronkelijke tekst werd er vrijwel niet -aan ML gedaan. - -Hier nog even een overzicht van de onderwerpen die in de VDP -cursus deel 1 t/m 9 zijn behandeld: - -1. VDP registers lezen/schrijven -2. Overzicht VDP registers en VRAM lezen/schrijven -3. Commandoregisters (1) -4. Commandoregisters (2) -5. Statusregisters -6. Sprites -7. Opslag schermen in VRAM (1) -8. Opslag schermen in VRAM (2) -9. Opslag schermen in VRAM (3) - -Vanaf deel 10 (dit deel staat op Sunrise Magazine #5) worden -praktijkvoorbeelden behandeld. Er is verder nog een VDP -cursus Extra, speciaal voor MSX2+. Dit deel zal uiteraard -ook worden herhaald. Ik zal verder nog een deel "Opslag -schermen in VRAM (4)" schrijven, waarin SCREEN 10 t/m 12 aan -bod komen. Op deze Sunrise Special ook de herhaling van deel -2. - -Tot de volgende keer! - -Stefan Boer \ No newline at end of file diff --git a/Sunrise Special/2/VDP Cursus 2.md b/Sunrise Special/2/VDP Cursus 2.md deleted file mode 100644 index b1040e2..0000000 --- a/Sunrise Special/2/VDP Cursus 2.md +++ /dev/null @@ -1,455 +0,0 @@ -# M S X 2 / 2 + V D P C U R S U S ( 2 ) - - -## I N L E I D I N G - -Dit is het tweede deel van de VDP cursus op herhaling. Deze -keer zal ik een overzicht geven van een groot aantal VDP -registers. Ze worden niet op volgorde van nummer behandeld, -maar in groepjes bij elkaar. - -De belangrijkste wijziging ten opzichte van de oude versie -is dat er nu bij het lezen/schrijven van VRAM meer aandacht -wordt besteed aan ML. - - -## M O D E R E G I S T E R S -``` - MSB 7 6 5 4 3 2 1 0 LSB -R#0 0 DG IE2 IE1 M5 M4 M3 0 Mode Register 0 -R#1 0 BL IE0 M1 M2 0 SI MAG Mode Register 1 -R#8 MS LP TP CB VR 0 SPD BW Mode Register 2 -R#9 LN 0 S1 S0 IL E0 NT DC Mode Register 3 - -R#0: DG : digitaliseren - IE2: 1 = interrupt van lichtpen of muis mogelijk - IE1: 1 = interrupt mogelijk bij bepaalde beeld- - lijn (zie R#19) -R#1: BL : scherm aan/uit (0=uit) - IE0: 1 = normale interrupt mogelijk - SI : 1 = sprite grootte 16x16, 0 = 8x8 - MA : 1 = vergrote sprites, 0 = normale sprites -``` -De schermmodi kunnen worden ingesteld met M1-M5: -``` - M5 M4 M3 M2 M1 -SCREEN 1 (G1) 0 0 0 0 0 -SCREEN 0 (T1) 0 0 0 0 1 (WIDTH 40) -SCREEN 3 (MC) 0 0 0 1 0 -SCREEN 2 (G2) 0 0 1 0 0 -SCREEN 4 (G3) 0 1 0 0 0 -SCREEN 0 (T2) 0 1 0 0 1 (WIDTH 80) -SCREEN 5 (G4) 0 1 1 0 0 -SCREEN 6 (G5) 1 0 0 0 0 -SCREEN 7 (G6) 1 0 1 0 0 -SCREEN 8 (G7) 1 1 1 0 0 -``` -De tekens tussen haakjes achter de schermmodi zijn de -offici�le benamingen. (T=TEXT, G=GRAPHIC, MC=MULTI COLOR) -``` -R#8: MS : 1 = color bus input / muis mogelijk - 0 = color bus output / geen muis mogelijk - LP : 1 = lichtpen mogelijk, 0 = geen lichtpen - TP : 1 = kleur 0 niet meer transparant - CB : 1 = color bus input, 0 = color bus output - VR : kies soort VRAM - 1 = 64K x 1 bit of 64K x 4 bits - 0 = 16K x 1 bit of 16K x 4 bits - SPD: 1 = sprites uit, 0 = sprites aan - BW : 1 = zwart/wit in 32 grijstinten, 0 = kleur -R#9: LN : Bepaal hoogte van scherm. 1=212, 0=192 - S0/1: Synchronisatiemode: - S1: S0: - 0 0 intern - 0 1 mix - 1 0 extern (digitize) - 1 1 niet - IL : 1 = interlace - EO : 1 = afwisselen even/oneven PAGE - NT : 0 = NTSC 60 Hz, 1 = PAL 50 Hz - DC : 1 = *DLCLK input, 0 = *DLCLK output -``` - -## T A B L E B A S E A D D R E S S R E G I S T E R S - -Deze adressen geven aan waar de diverse tabellen in het VRAM -beginnen. Dit komt overeen met BASE(n) in BASIC. -``` - MSB 7 6 5 4 3 2 1 0 LSB -R#2 0 A16 A15 A14 A13 A12 A11 A10 scherminfotabel -R#3 A13 A12 A11 A10 A9 A8 A7 A6 kleurtabel low -R#10 0 0 0 0 0 A16 A15 A14 kleurtabel high -R#4 0 0 A16 A15 A14 A13 A12 A11 patroontabel -R#5 A14 A13 A12 A11 A10 A9 A8 A7 sprite-info low -R#11 0 0 0 0 0 0 A16 A15 sprite-info high -R#6 0 0 A16 A15 A14 A13 A12 A11 sprite-patroon -``` -In BASIC kun je deze adressen opvragen met BASE(n). n moet -dan gelijk zijn aan vijf maal de screenmode plus: -0: scherminfo : SCREEN 0-4: patroonnummers - SCREEN 5-8: bitmapped -1: kleur : alleen SCREEN 0-4 (beh. WIDTH 40) -2: patroon : alleen SCREEN 0-4 -3: sprite-info : coordinaten e.d. -4: sprite-patroon : sprite$()="..." - -Voorbeeld: de sprite-info tabel van SCREEN 7 begint dus op -de waarde die in BASE(5*7+3) staat. - -Je kunt met behulp van deze registers in SCREEN 0-4 zeer -veel schermen tegelijk in het VRAM zetten, omdat die -schermen maximaal 16 kB per page nodig hebben, en je hebt -128 kB. Uitleg over hoe de beeldinformatie wordt opgeslagen -in deel 7 t/m 9. - -Je kunt aan de gegevens ook zien waarvan de BASE(n) waarden -een veelvoud moeten zijn. Als je je daaraan niet houdt, -volgt er een foutmelding. Bijvoorbeeld de spritepatroon- -tabel. Het laagste bit dat door R#6 wordt bepaald is A11. -Het moet dus een veelvoud zijn van 2^11 = 2048. - -Zie verder deel 7 t/m 9. - - -## K L E U R R E G I S T E R S -``` - MSB 7 6 5 4 3 2 1 0 LSB -R#7 TC3 TC2 TC1 TC0 BD3 BD2 BD1 BD0 Tekst/Achtergr -R#12 T23 T22 T21 T20 BC3 BC2 BC1 BC0 Blinkkleuren -R#13 ON3 ON2 ON1 ON0 OF3 OF2 OF1 OF0 Blinktijden - -TC3-TC0 : tekstkleur in T1 en T2 -BD3-BD0 : achtergrondkleur in alle schermmodi -T23-T20 : tekstkleur voor blink in T2 -BC3-BC0 : achtergrondkleur voor blink in T2 -ON3-ON0 : tijd voor blink-kleur -OF3-OF0 : tijd voor normale kleur -``` -Je kunt R#13 ook gebruiken om de PAGEs van SCREEN 5-8 -afwisseld weer te geven. Stel met SET PAGE de weergegeven -PAGE op 1 of 3, en zet dan de gewenste tijden in R#13. PAGE -1 en 0 (resp. 3 en 2) zullen dan beurtelings worden getoond. -Voorbeeld: SET PAGE 1 : VDP(14)=&H66 'page 0 en 1 worden nu -beurtelings getoond met een tussenpauze van ca. 1 seconde. - - -## U I T L E G B I J B L I N K M O D E - -Je kunt in SCREEN 0, WIDTH 80 (T2 mode) alternatieve scherm- -kleuren gebruiken. Er is hiervoor een speciale tabel -gereserveerd in het VRAM. Het beginadres daarvan staat in -BASE(1). In die tabel staat voor elke schermpositie 1 bit. -Is dat bit gelijk aan 1, dan wordt de alternatieve kleur -getoond. Is het bit gelijk aan 0, dan wordt de normale kleur -getoond. Eventueel kun je de alternatief gekleurde delen van -het scherm ook nog laten knipperen. De knippertijd moet in -R#13 worden gezet. Dat gaat in ongeveer 1/6 seconde -nauwkeurig. De hoogste vier bits bepalen de tijd voor de -alternatieve kleur, de laagste vier bits bepalen de tijd -voor de normale kleur. In R#12 (VDP(13)) staan de -alternatieve kleuren. De bovenste vier bits de voorgrond- en -de onderste vier bits de achtergrondkleur. Zet de waarde -&H10 in R#13 (VDP(14)) als je niet wilt knipperen, maar de -alternatieve kleur constant wilt tonen. - -De blinkertabel is als volgt ingedeeld: -BASE(1)+ 0: posities ( 0, 0)...( 7, 0) -BASE(1)+ 1: posities ( 8, 0)...(15, 0) -BASE(1)+ 9: posities (72, 0)...(79, 0) -BASE(1)+ 10: posities ( 0, 1)...( 7, 1) -BASE(1)+239: posities (72,23)...(79,23) - -Blinktijden (60 Hz, VDP(10)=0, NTSC, milliseconde): -Data: (hex) Tijd: (ms) Data: (hex) Tijd: (ms) ------------------------------------------------------------- -0 0 8 1335.1 -1 166.9 9 1501.9 -2 333.8 A 1668.8 -3 500.6 B 1835.7 -4 667.5 C 2002.6 -5 834.4 D 2169.5 -6 1001.3 E 2336.3 -7 1168.2 F 2503.2 ------------------------------------------------------------- - -Voorbeeld: je wilt de posities (12,3), (14,3) en (50,12) -laten knipperen met voorgrondkleur magenta (13) en achter- -grondkleur donkerblauw (4). De normale kleur moet 500.6 ms -getoond worden, de alternatieve kleur 166.9 ms. - -Eerst berekenen we de adressen: -14 \ 8 = 1 > Het adres wordt dus: BASE(1)+30+1 -14 MOD 8 = 6 > Het ene bitnummer wordt 7 - 6 = 1 en -12 MOD 8 = 4 > het andere bitnummer wordt 7 - 4 = 3, dus -3 * 10 = 30 > de te VPOKEn waarde is &B00001010 = 10 - -50 \ 8 = 6 > Het adres wordt dus: BASE(1)+120+6 -50 MOD 8 = 2 > Het bitnummer wordt 7 - 2 = 5, dus de te -12 * 10 = 120 > VPOKEn waarde is &B00100000 = 32 - -In de tabel vinden we voor de blinktijden de waardes 3 en 1. -13 is gelijk aan &HD. Dat lever totaal op: -VPOKE BASE(1)+31,10: VPOKE BASE(1)+126,32: VDP(13)=&HD4: -VDP(14)=&H13 - -N.B. Op Sunrise Special #2 staat een uitgebreid artikel over -een standaard ML routine voor de blinkmode en vier nieuwe -BASIC commando's (CMD BCOL, CMD BFIL, CMD BTIM en CMD BRES), -waarmee de blink mode eenvoudig vanuit BASIC te besturen is. - - -## C O L O R B U R S T R E G I S T E R S -``` - MSB 7 6 5 4 3 2 1 0 LSB -R#20 0 0 0 0 0 0 0 0 Color burst 1 -R#21 0 0 1 1 1 0 1 1 Color burst 2 -R#22 0 0 0 0 0 1 0 1 Color burst 3 -``` -Ik weet nog steeds niet waar deze registers voor dienen. Als -iemand het weet, graag even een briefje naar de Sunrise -postbus t.a.v. ondergetekende. Ik denk overigens dat deze -registers in het geheel geen nut hebben voor de programmeur, -het schrijven van willekeurige waardes naar deze registers -heeft namelijk geen enkel merkbaar effect. - -## D I S P L A Y R E G I S T E R S -``` - MSB 7 6 5 4 3 2 1 0 LSB -R#18 V3 V2 V1 V0 H3 H2 H1 H0 Display adjust -R#23 DO7 DO6 DO5 DO4 DO3 DO2 DO1 DO0 Display offset -R#19 IL7 IL6 IL5 IL4 IL3 IL2 IL1 IL0 Interrupt line -``` -R#18 werkt ongeveer net zo als SET ADJUST(dx,dy) in Basic. -Het bepaalt de positie van het beeld op het scherm. -LINKS: H=7...H=1 MIDDEN: H=0 RECHTS: H=15...H=8 -ONDER: V=8...V=15 MIDDEN: V=0 BOVEN: V=1...V=7 -Dit register wordt vaak op de MSX2 gebruikt om een horizon- -tale scroll te maken. Denk hierbij aan Space Manbow, -Golvellius 2, Super Cooks, Pennant Race 2. Je ziet dan een -happende rand. Op de MSX2+ wordt de scroll dan meestal -beter. - -Met R#23 (beter bekend als VDP(24)) kun je zeer eenvoudig -een verticale scroll maken op de MSX2. Een van de volgende -keren zal ik een programmavoorbeeld hiervan laten zien. De -waarde in VDP(24) geeft aan op welke hoogte de bovenste lijn -van het scherm zich bevindt. - -Met R#19 kun je aangeven bij welke beeldlijn de VDP een -interrupt moet geven. (Zie ook R#0). Je hebt dit register -nodig voor screensplits. Bij een screensplit kun je een -bepaalde actie (bijvoorbeeld een pagewissel, schermwissel, -kleurwissel, scrollen, etc.) laten uitvoeren, op het moment -dat de VDP een bepaalde beeldlijn naar het beeldscherm -stuurt. Ik zal hier nu verder niet op in gaan, een -screensplit zal bij de praktijkvoorbeelden (deel 10 en -verder van de VDP cursus) zeker aan bod komen. - - -## A C C E S R E G I S T E R S - -Deze registers gebruik je bij lezen/schrijven van VDP- -registers en VRAM. -``` - MSB 7 6 5 4 3 2 1 0 LSB -R#14 0 0 0 0 0 A16 A15 A14 VRAM Base -R#15 0 0 0 0 S3 S2 S1 S0 S# pointer -R#16 0 0 0 0 C3 C2 C1 C0 Color palette -R#17 AII 0 RS5 RS4 RS3 RS2 RS1 RS0 R# pointer -``` -Over het gebruik van R#15-17 heb ik in deel 1 al het een en -ander uitgelegd. Daarom hier alleen kort de werking: -R#15 Statusregister pointer. Schrijf het nummer van het te - lezen statusregister naar R#15. De data komt in Port - #1. -R#16 Color palette pointer. Schrijf het color palette - nummer naar R#16. Schrijf daarna de kleurdata naar - Port #2. Doe dat als volgt (binair): - 1e byte: 0 R1 R2 R0 0 B2 B1 B0 - 2e byte: 0 0 0 0 0 G2 G1 G0 - De waarde van R#16 wordt automatisch verhoogd, zodat - meerdere palet entries kunnen worden veranderd zonder - eerst het nummer naar R#16 te moeten schrijven. -R#17 Indirekte VDP-beschrijving. Schrijf het registernummer - naar R#17. Schrijf daarna de data die naar dat - register moet naar Port #3. Als je wilt dat het regis- - ternummer automatisch verhoogd wordt, moet je het AII - bit op 0 zetten. - -(Het schrijven naar Port #0 t/m Port #3 gebeurt met -OUT-instrukties. De I/O adressen voor Port #0 t/m Port #3 -zijn altijd &H98 t/m &H9B.) - - -## L E Z E N / S C H R I J V E N V R A M - -Om het VRAM te lezen/schrijven moet je de volgende procedure -volgen: - -1) Bankswitching. In principe is dit niet nodig, omdat -normaal gesproken altijd het normale VRAM is geselecteerd. -Sommige computers hebben 64 kB expansion VRAM, dit kan -gebruikt worden door bankswitching toe te passen. in R#45 -aan of je het VRAM (0) of het Expansion RAM (1) wilt -gebruiken. Plaats de overeenkomstige waarde in bit 6. - MSB 7 6 5 4 3 2 1 0 LSB -R#45 0 MXC MXD MXS DIY DIX EQ MAJ Argument Reg. -MXD = 0 betekent VRAM, 1 betekent Exp RAM - -2) Het VRAM adres kan vari�ren van 0-1FFFFH (128 kB). Plaats -de drie hoogste bits in R#14: - MSB 7 6 5 4 3 2 1 0 LSB -R#14 0 0 0 0 0 A16 A15 A14 VRAM Base -(Vanaf hier is het MSX1 compatible.) - -3) Schrijf de acht laagste bits naar Port #1. - MSB 7 6 5 4 3 2 1 0 LSB -Port #1 A7 A6 A5 A4 A3 A2 A1 A0 First Byte - -4) Schrijf de bits 8-13 naar Port #1. Bepaal lezen/ -schrijven met bit X. X=1: Schrijven, X=0: Lezen. - - MSB 7 6 5 4 3 2 1 0 LSB -Port #1 0 X A13 A12 A11 A10 A9 A8 Second Byte - -N.B. Bit 7 moet 0 zijn, hieraan kan de VDP zien dat de -waarde die hij zojuist ontvangen heeft niet naar een VDP -register moet (dan is bit 7 namelijk 1), maar dat het de -bits 0-7 van het adres zijn. Voor bit 6 en 7 geldt dus het -volgende: - -b7 b6 -1 0 VDP register schrijven -0 0 VRAM lezen -0 1 VRAM schrijven - -5) Lees of schrijf de data van/naar Port #0 (I/O poort -&H98). Het adres wordt automatisch verhoogd, dus je kunt -continu doorgaan met het lezen of schrijven van data. - -Het lezen/schrijven van VRAM kan weer op drie manieren, -namelijk in BASIC, in machinetaal via BIOS en in machinetaal -door rechtstreeks de VDP aan te sturen met IN en OUT. - -In BASIC gaat het uiteraard gewoon met VPOKE, de BASIC -interpreter zorgt voor de rest. In het BIOS zijn de volgende -routines aanwezig voor het lezen/schrijven van VRAM: - - MSX2: - -&H016E NSETRD Stel VDP in om VRAM te lezen vanaf adres - in HL. Na het aanroepen van deze routine - kan de data uit Port #0 worden gelezen. -&H0171 NSTWRT Stel VDP in om VRAM te schrijven vanaf - adres in HL. Na het aanroepen van deze - routine kan de data naar Port #0 worden - geschreven. -&H0174 NRDVRM Lees VRAM. HL=adres, A=data, wijzigt F. -&H0177 NWRVRM Schrijf VRAM. HL=adres, A=data, - wijzigt AF. -N.B. NRDVRM en NWRVRM gebruiken NSETRD en NSTWRT. - - MSX1/2: -&H004A RDVRM Zie NRDVRM, alleen SCREEN 0-4! -&H004D WRTVRM Zie NWRVRM, alleen SCREEN 0-4! -&H0050 SETRD Zie NSETRD, alleen SCREEN 0-4! -&H0053 SETWRT Zie NSTWRT, alleen SCREEN 0-4! - -(De hierboven genoemde routines zijn gemaakt voor de MSX1, -en kunnen daarom alleen adressen tussen 0 en 16383 aan. Dit -is in SCREEN 0-4 geen bezwaar, maar in SCREEN 5-12 wel. Op -een MSX2 programma gewoon altijd NRDVRM, NWRVRM, NSETRD en -NSTWRT gebruiken, ook in SCREEN 0-4. RDVRM en WRTVRM -gebruiken SETRD en SETWRT.) - -0056H FILVRM Vult blok VRAM vanaf HL met lengte BC met - waarde A. Wijzigt: AF,BC. -0059H LDIRMV Kopieert blok VRAM->RAM. HL=bron, DE=doel, - BC=lengte. Wijzigt: alle. -005CH LDIRVM Kopieert blok RAM->VRAM. Zie LDIRMV -016BH BIGFIL Doet hetzelfde als FILVRM. Het verschil is - dat FILVRM bij SCREEN 0-3 net doet alsof er - maar 16 kB, en BIGFIL niet. - -Soortgelijke routines zijn ook in het SUBROM aanwezig, maar -aangezien het aanroepen daarvan alleen maar extra tijd in -beslag neemt laat ik dat hier achterwege. - -Nu rechtstreeks in ML. Ik geef hier de routines NSTWRT en -NSETRD. Deze routines zijn praktisch gelijk aan de routines -in het MAIN ROM, die kunt u dus rustig gebruiken. Deze -routines zijn dan ook vooral leerzaam! - -``` -; VRAM routines door Stefan Boer -; VDP cursus op herhaling deel 2 -; Sunrise Special #2 -; Door Stefan Boer -; (c) Sunrise 1992 - -; SETWRT -; Zet VDP klaar om naar VRAM te schrijven -; In: HL: bit 0-15 van adres -; C : bit 16 van adres - -SETWRT: LD A,H - RES 7,A - SET 6,A ; 0 1 is VRAM schrijven - JP RDWRT - -; SETRD -; Zet VDP klaar om uit VRAM te lezen -; In: HL: bit 0-15 van adres -; C: bit 16 van adres - -SETRD: LD A,H - AND &B00111111 ; 0 0 is VRAM lezen - -; Dit gedeelte is voor beide routines hetzelfde - -RDWRT: PUSH AF ; deze byte moet pas als - ; laatste naar Port #1 - LD A,C ; bit 16 van adres - AND 1 ; alleen bit 0 - LD C,A - LD A,H - AND &HC0 ; alleen bit 6 en 7 - ; (bit 14 en 15 van adres) - OR C ; bit 16 van adres erbij - RLCA - RLCA ; schuif bit 0, 6 en 7 naar - ; bit 0, 1 en 2 - DI - OUT (&H99),A - LD A,14+128 - OUT (&H99),A ; schrijf bit 14-16 van adres - ; naar R#14 - LD A,L ; bit 0-7 van adres - OUT (&H99),A ; naar Port #1 - POP AF ; bit 8-13 van adres, plus VDP - ; instructie - OUT (&H99),A ; naar Port #1 - EI - RET - -; data kan nu worden gelezen/geschreven via Port #0 (&H98) -``` -Deze routine spreekt voor zichzelf, u kunt de eerder -omschreven standaardprocedure hierin herkennen. - - -## T E N S L O T T E - -Met vragen over de VDP cursus kunt u natuurlijk altijd bij -mij terecht, net als met alle andere programmeervragen -overigens. Schrijf een briefje naar de Sunrise postbus, -t.a.v. ondergetekende. - -Op de volgende Sunrise Special zullen deel 3 en 4 van de VDP -cursus worden herhaald, daarin worden de commando registers -van de VDP behandeld. Hiermee kunt u zelf COPY's, LINEs, -etc. in machinetaal programmeren! - -Tot de volgende keer! - -Stefan Boer \ No newline at end of file diff --git a/Sunrise Special/3/De archeologie van de MSX.md b/Sunrise Special/3/De archeologie van de MSX.md deleted file mode 100644 index 6e3d3e6..0000000 --- a/Sunrise Special/3/De archeologie van de MSX.md +++ /dev/null @@ -1,222 +0,0 @@ -# D E A R C H E O L O G I E V A N D E M S X - - -Ofwel: waarom een vooruitziende blik achteraf beter was -geweest - -## I N L E I D I N G - -De tegenwoordige MSX2, MSX2+ of turbo R computers lijken -maar in weinig opzichten op hun MSX1-voorgangers van bijna -tien jaar geleden. De vroege MSX1 computers waren ontworpen -om vooral zo goedkoop mogelijk te zijn, en maakten dus -uitsluitend gebruik van goedkope standaardcomponenten, die -goed verkrijgbaar waren. De belangrijkste (LSI) componenten -waren: - -Type Taken Fabrikant(en) ------------------------------------------------------------- -Z80A processor Zilog, SGS, etc. -AY-3-8910 geluid, joystickpoorten General Instruments -8255 PPI toetsenbord, slotselectie Intel - cassette, diverse led's -9918A VDP display Texas Instruments - -Voor de rest kon gebruik gemaakt worden van standaard -(LS)TTL-, RAM- en EPROM IC's, aangevuld met wat ander spul -(zoals weerstanden, condensatoren, etc.) zodat een ervaren -hobbyist in principe zijn eigen MSX1 had kunnen bouwen met -componenten die bijna iedere electronicazaak kon leveren. - -Hoewel de gebruikte LSI-componenten niet erg duur waren, -bleken ze toch duur genoeg om er zo weinig mogelijk van te -gebruiken, hoewel bijvoorbeeld een extra 8255 de hardware -eenvoudiger had gehouden en de prestaties had verbeterd. Zo -is er bijvoorbeeld tussen de joystickpoorten en de 8910 -extra hardware nodig om tussen de twee joysticks (of wat er -ook aan die poorten zit) te schakelen, domweg omdat er -onvoldoende I/O lijnen beschikbaar zijn. - -Het lijkt er wel op of die tweede joystickpoort pas in een -later stadium aan de standaard is toegevoegd, en hetzelfde -kun je zeggen van de printerpoort, die op veel vroege -MSX-computers ontbrak. (Philips heeft ooit eens een -cartridge uitgebracht met alleen een printeraansluiting -erop!) - - -##H E T G E H E U G E N - P R O B L E E M - -De Z80 kan helaas niet meer dan 64 kB aan geheugen -adresseren, en dat was zelfs toendertijd te weinig, vooral -omdat er naast een verplichte BASIC-interpreter ook nog -software in cartridges moest kunnen lopen, en aan het toen -nog toekomstige MSX-DOS zal men ook wel gedacht hebben. - -Dit probleem is - zoals iedereen wel zal weten - opgelost -door de PPI-poort op 0A8h te gebruiken om voor de selectie -van de geheugenslots te dienen. Omdat we vier pagina's -moeten schakelen, en dat in een enkel byte moeten kunnen -doen, beperkt dat ons tot 2 bits per pagina, en dus een -maximum van vier slots. Dit lijkt het adresseerbare geheugen -uit te breiden to 4 x 64 = 256 kB, maar schijn bedriegt: ten -eerste mag pagina 3 nooit worden weggeschakeld, omdat daar -de systeemvariabelen in zitten en (meestal en hopelijk) de -stack, en ten tweede omdat het wegschakelen van pagina 0 de -BIOS onbereikbaar maakt, tenzij je ervoor zorgt dat er in -die pagina ook slotselectieroutines aanwezig zijn. (MSX-DOS -doet dit, maar daarover later meer.) - - -##H E T S E C U N D A I R E S L O T R E G I S T E R - -Achteraf gezien zal het dan ook niemand verbazen dat dit te -weinig bleek, maar wat wel verbazend is, is de manier waarop -men het heeft opgelost: het secundaire slotselectieregister -op 0FFFFh! - -Op zich is het natuurlijk al vreemd om een memory-mapped -register te gebruiken als er nog voldoende ongebruikte I/O -adressen zijn, maar dat kun je hoogstens een -schoonheidsfoutje noemen. Nee, waar het echte probleem ligt -is het feit dat ieder geâxpandeerd slot een eigen, -afzonderlijk slotselectie-register op 0FFFFh heeft! Dit feit -en wat de consequenties hiervan zijn realiseren maar heel -weinig mensen zich ten volle, dus laat ik ze hier op een -rijtje zetten: - -In pagina 3 zit een deel van de slotselectieroutines -(behalve voor ENASLT), en om een goede reden: als we van -(primair) slot veranderen is dat de enige pagina waarvan we -zeker weten dat hij op z'n plaats blijft na het schakelen. -Het ongelukkige van het secundaire slotregister op 0FFFFh -zit hem hierin, dat we juist pagina 3 moeten wegschakelen om -het secundaire slotregister te kunnen bereiken, waardoor een -secundaire slots selecteren nogal omslachtig wordt (de -stappen met een * gebeuren in pagina 3): - -1 - Schakel het gewenste primaire slot in, maar op pagina 3 -2 - Lees FFFF, complementeer, en onthoud de waarde -3 - Bereken de nieuwe waarde, en schrijf naar FFFF -4 - Herstel primair slot (situatie als voor 1) -5 - Bereken nieuw primair slot op de gewenste pagina -6* - Schrijf primair slotregister -7* - De gewenste actie (lezen, schrijven of CALLen) -8* - Herstel primair slotregister (situatie als voor 1) -9 - Schakel primair slot als bij 1 -10 - Schrijf oude waarde (uit 2) terug naar FFFF -11 - Herstel primair slotregister (situatie als voor 1) - - -Voor ongeâxpandeerde slots gaat 't simpeler: - -1 - Bereken nieuw primair slot op de gewenste pagina -2* - Schrijf primair slotregister -3* - De gewenste actie (lezen, schrijven of CALLen) -4* - Herstel primair slotregister (situatie als voor 1) - - -##D E C O N S E Q U E N T I E S - -Die ingewikkelde secundaire slotselectie is niet zonder -gevolgen. Zo moet iedere slotselectieroutine heen en weer -hinken tussen pagina 3 en (meestal) 0, terwijl het heel -handig (en een stuk sneller) zou zijn als we de complete -routine in pagina 3 kwijt zouden kunnen. MSX-DOS heeft -hetzelfde probleem, en heeft het leeuwendeel van de routines -in pagina 3 zitten, maar een deel zit verplicht in pagina 0. - -Een tweede gevolg is dat binnen een geâxpandeerd slot geen -CALSLT ed. gedaan kan worden naar pagina 0, of het moest via -aan omweg zijn! Dit kan uiterst onaangename consequenties -hebben voor computers met RAM en SUBROM in hetzelfde -geâxpandeerde slot, of (erger nog!) met een geâxpandeerd -slot 0. In het eerste geval moet een omweg via de BIOS (de -routine EXTROM) gemaakt worden, wat lastig wordt gemaakt -door het feit dat CALSLT ook het IX-register gebruikt. - -Dus waarom hebben ze het zichzelf zo ingewikkeld gemaakt? -Een deel van het antwoord ligt in het feit dat men -secundaire sloten herkent doordat bij teruglezen de waarde -wordt gecomplementeerd. Als men van dit gemak had afgezien - -de RAM en ROM check bij het opstarten van de computer wordt -dan iets ingewikkelder - dan hadden de secundaire -slotselectie registers write-only kunnen worden uitgevoerd. -In dat geval hoefde de hardware rond die registers er niet -op te letten of het desbetreffende primaire slot is -ingeschakeld, en bovendien kon de hardware voor het -teruglezen vervallen. (Het leuke is namelijk dat niet alleen -alle in het systeem aanwezige secundaire -slotselectieregisters beschreven worden, maar ook het gewone -RAM op 0FFFFh, zodat teruglezen nog steeds zonder meer -mogelijk is!) - -Dus ten koste van iets ingewikkelder software kan de -hardware eenvoudiger en bovendien vervallen dan bijna alle -bovenstaande bezwaren! (Naar het secundaire slotregister kan -dan nl. altijd geschreven worden, ook vanuit pagina 3. -Secundaire slotselectie wordt dus veel eenvoudiger.) Een -onbegrijpelijke misser! Je moet hier wel de conlusie uit -trekken dat het secundaire slot een late en weinig -doordachte toevoeging aan het MSX-systeem is. - - - -##H E T I N T E R R U P T S Y S T E E M - -Ook het interruptsysteem draagt de sporen van spaarzaam -denken. Interrupts veroorzaken altijd een sprong naar adres -38h, wat tot gevolg heeft dat daar natuurlijk altijd iets -aanwezig moet zijn om de interrupts af te handelen. (En er -moeten ook slotselectieroutines aanwezig zijn!) Deze -interrupt wordt altijd in de BIOS afgehandeld voor hij de zo -bekende hooks op FD9A en FD9F passeert. Dit heeft tot gevolg -dat een echt snelle interruptafhandeling niet mogelijk is, -zeker in DOS, waar er nog een extra interslot-call aan te -pas moet komen. - -Nvdr. BIOS wegschakelen en zelf iets op 38h zetten -misschien? - -Dat vaste interruptadres veroorzaakt bovendien nogal eens -problemen met CP/M debuggers, omdat adres 38h vaak door die -programma's wordt gebruikt. Beter ware het geweest om met -behulp van een PIC (priority interrupt controller) zoals de -8259 van Intel interrupt-vectoring te verzorgen, iets wat -nauwelijks extra kosten met zich had meegebracht, maar het -systeem wel een stuk sneller en flexibeler had gemaakt. - - -##D E V I C E S - -Aan de andere kant is het vreemd dat juist een doordacht -systeem als het device-systeem op de MSX nooit gebruikt -wordt; iets dat waarschijnlijk alleen toe te schrijven is -aan gebrek aan informatie (hoewel gebrek aan devices -natuurlijk ook kan). Om vooral geen slapende honden wakker -te maken zal ik volstaan met te zeggen dat dit (onder -andere) gaat via de hook B.EXT (FFCA), een hook die ook door -MemMan wordt gebruikt, hoewel deze beslist geen device is! -Buiten de devices die standaard in BASIC zitten (CRT: GRP: -CAS: LPT:) kunnen RS232-uitbreidingen (COM:) hiermee ook -worden gebruikt. - - -##C O N C L U S I E - -Bij het uitdenken van het MSX-systeem is goed nagedacht, -maar er zijn ook blunders gemaakt. Iedere computer is -natuurlijk een compromis tussen wensen en kosten, en -persoonlijk verbaast het mij dat het systeem telkens kon -worden uitgebreid zonder dat de compatibiliteit tussen de -systemen in belangrijke mate verloren ging. - -Wat betreft het secundaire slot systeem kun je je afvragen -of alle programmeurs wel precies weten hoe het werkt. Alle -Philips MSX2 computers hebben het RAM in het geâxpandeerde -slot 3 zitten, wat inhoudt dat het secundaire slotregister -altijd bereikbaar is. Programma's die rucksichtslos op FFFF -lezen of schrijven zullen op die computers wel werken, maar -kunnen op andere voor grote problemen zorgen. - -Robert Amesz diff --git a/Sunrise Special/3/De programmeertaal C deel 3.md b/Sunrise Special/3/De programmeertaal C deel 3.md deleted file mode 100644 index db181cd..0000000 --- a/Sunrise Special/3/De programmeertaal C deel 3.md +++ /dev/null @@ -1,616 +0,0 @@ -# D E P R O G R A M M E E R T A A L C - D E E L 3 - -## I N L E I D I N G - -Voor BASIC programmeurs is het gebruik van strings net zo -gemakkelijk als getallen: BASIC zoekt zelf wel uit hoe lang -strings zijn en waar ze in het geheugen terecht moeten -komen. PASCAL programmeurs hebben het wat moeilijker, -aangezien PASCAL eigenlijk geen strings kent (alleen ARRAYS -OF CHAR). In Turbo Pascal hebben ze dit probleem opgelost -door een van ARRAY OF CHAR afgeleid type, de STRING (hoe -verzinnen ze het, he?) te introduceren. Wel moet nog steeds -de maximale lengte worden gespecificeerd. - -Wat dat betreft lijkt C wel op Turbo Pascal, alleen zijn er -wat andere conventies wat betreft het gebruik van strings. -Strings in C zijn zo verweven met array's en pointers, dat -het zinloos zou zijn te proberen deze dingen los van elkaar -te behandelen. Maar om te beginnen zullen we moeten weten -hoe we moeten werken met array's in C. - - -## D E A R R A Y - -Een array is een rij variabelen van hetzelfde type, die elk -afzonderlijk kunnen worden aangesproken door middel van een -index. (Onthoud dit woord; het zal nog vaak gebruikt -worden!) Een array laat zich nog het best vergelijken met -een rij huizen, die allemaal identiek zijn. Als je naar een -bepaald huis in de rij wilt verwijzen zul je naast de -straatnaam (de naam van het array) ook het huisnummer moeten -gebruiken (de index). Ook in C is de index een getal. - -Om een array binnen C te declareren gaan we bijna hetzelfde -te werk als bij gewone variabelen. Zo algemeen mogelijk -geformuleerd: - - []; - -Hierbij is de al aan ons bekende datatypen (int, char -enz.), is de naam van het array en is het -aantal elementen van het array. Met - - int getallen[10]; - -creâren we dus een array 'getallen', bestaande uit 10 int's. -Met - - char buffer[80]; - -maken we een array 'buffer' van 80 char's. In C is de -laagste index altijd 0, en in bovenstaand voorbeeld is de -hoogste index 79. Dan hebben we totaal 80 elementen. Dus in -een array van N elementen loopt de index van 0 t/m N-1. LET -HIER GOED OP! In C wordt niet gecontroleerd of de index die -we gebruiken binnen deze grenzen valt, en dit kan tot zeer -venijnige bug's leiden, vooral als we iets in zo'n -niet-bestaand element willen opslaan! - -Overigens, de vierkante haakjes slaan alleen op de naam die -er direkt voor staat. Met - - int veel[40], enkel; - -declareren we dus een array 'veel' met 40 int's en een -gewone int-variabele, 'enkel'. -Een element uit een array gebruiken in een uitdrukking kan -als volgt: - - [] - -De is een gewone uitdrukking, en het is uiteraard -geen bezwaar als daarin ook weer elementen van een array -worden gebruikt. De volgende uitdrukkingen in C zijn dus -allemaal correct (ervan uitgaande dat de gebruikte -variabelen zijn gedeclareerd): - - buffer[0] - - getallen[x] - - getallen[x-1] - - buffer[getallen[x-1] + 1] - -Een en andere kan zo ingewikkeld worden als de -omstandigheden vereisen, zolang de index maar binnen de -juiste grenzen valt. Verwijzingen naar elementen mogen -overal gebruikt worden als gewone variabelen. Dus met - - getallen[x+1] = getallen[x] * 2; - -heeft C geen enkele moeite. - - -## P O I N T E R S - -Verwant met de array (nauwer zelfs dan je op het eerste -gezicht zou denken) is de pointer. Een pointer is een -variabele die 'wijst' naar een andere variabele. (Vandaar -pointer, want 'to point' is 'wijzen naar'). Om de variabele -waarnaar zo'n pointer wijst aan te kunnen spreken, of - -omgekeerd - van een variabele de verwijzing (d.w.z. het -adres) op te vragen zijn er in C een tweetal operatoren, -resp. de '*' en de '&'. Maar laten eerst eens beginnen met -het declareren van een pointer. Dit doen we met: - - *; - -Hiermee wordt dus een pointer gecreeerd die naar variabelen -van wijst. Een voorbeeld: met - - int *intptr; - -krijgen we een pointer 'intptr' die naar variabelen van het -type int wijst. Het sterretje heeft alleen betrekking op de -naam die er direkt achter staat. De declaratie - - int *intptr, x; - -creeert dus een gewone int-variabele 'x', en een -pointer-naar-int 'intptr'. We kunnen dus 'intptr' naar 'x' -laten wijzen! Dit kan met de '&' operator, die het adres van -een variabele levert. Met - - intptr = &x; - -wijst 'intptr' dus naar 'x'. Wil dit enig nut hebben dan -moeten we iets met die verwijzing kunnen doen. Met de '*' -operator krijgen we toegang tot de variabele waarnaar de -pointer wijst. Na - - intptr = &x; - *intptr = 3; - -zal 'x' dus de waarde 3 hebben gekregen. Dit is misschien -een beetje verwarrend, omdat we de '*' ook voor -vermenigvuldiging wordt gebruikt. Bij een vermenigvuldiging -heeft de '*' twee waarden nodig (en is dus een binaire -operator) en als verwijzing slechts 1 (een unaire operator). -Vergelijk dit bijvoorbeeld met de '-' operator, die zowel -'negatief maken' (unair) als 'aftrekken' (binair) betekent. -Omdat het vermenigvuldigen van pointers geen zinvolle -bezigheid is, kan er eigenlijk geen verwarring ontstaan. - -We kunnen ook naar een arrayelement wijzen. Dus met - - int getallen[10], *getal; - -declareren we een int-array 'getallen' en een -pointer-naar-int 'getal', waarna we met - - getal = &getallen[5]; - -'getal' naar het zesde (!) element van het array 'getallen' -zal wijzen. In sommige gevallen kan het echter nog simpeler -als we in element 0 - het eerste element van het array - -zijn geinteresseerd: - - getal = &getallen[0]; - -en - - getal = getallen; - -doen namelijk precies hetzelfde. Als we namelijk in C een -array declareren gebeuren er twee dingen: ten eerste wordt -er ruimte gereserveerd voor de elementen van het array. -Vervolgens wordt de pointer naar element 0 gekoppeld aan de -naam van het array. Een array is dus een bijzonder soort -pointer, maar dan een pointer die niet van waarde kan -veranderen! (Proberen we dit toch te doen dan volgt -(meestal) de wat cryptische foutboodschap: "Must be lvalue" -of: "Can't be rvalue". Dit is nog overgebleven uit de vroege -jaren van de taal C, en heeft te maken met de interne opslag -van informatie in de compiler zelf.) - -De slimmeriken onder ons zullen zich nu afvragen: "Als een -array een bijzonder soort pointer is, kunnen we dan pointers -net zo gebruiken als array's?" Het antwoord hierop luidt: -ja! De vierkante haken zijn eigenlijk niets anders dan de -zoveelste operator in C, maar dan eentje die - net als de -unaire '*' operator - alleen met pointers werkt. - -Een bijzonder geval is als een pointer NERGENS naar wijst. -Hiermee wordt niet bedoeld: naar een niet-bestaande -variabele, maar echt naar niets. Hiervoor is in STDIO.H de -waarde NULL gedefinieerd, en we kunnen met bijvoorbeeld - - getal = NULL - -de pointervariabele getal 'nergens' naar laten wijzen, en -met - - getal == NULL - -of - - getal != NULL - -kan getest worden of dit wel, resp. niet zo is. Het gebruik -van NULL berust in feite op een afspraak, en is zeer nuttig -in bepaalde algorithmen. Overigens zijn de '==' en de '!=' -operatoren de enige zinvolle vergelijkingsoperatoren voor -pointers. Men noemt twee pointers gelijk als ze naar -dezelfde variabele wijzen, of allebei NULL zijn. Pointers -kunnen natuurlijk eigenlijk alleen vergeleken worden als ze -ook naar hetzelfde type wijzen, als zijn er maar weinig -compilers die dit testen. Alleen NULL mag altijd gebruikt -worden, ongeacht het type waar de pointer naar wijst. - -Met pointers kan in zeer beperkte mate worden gerekend, en -dan alleen nog als pointers naar elementen van array's -wijzen. Kijk eens naar het volgende stukje C: - - int getallen[20], *ptr1, *ptr2; - ptr1 = &getallen[5]; - ptr2 = &getallen[10]; - -hierna doet - - *(ptr1 + 1) - -hetzelfde als - - getallen[6] - -En - - *(ptr1 + 3) - -komt overeen met - - getallen[8] - -Tenslotte, de uitdrukking - - ptr2 - ptr1 - -moet de waarde 5 opleveren. De meest gebruikte operator bij -pointers is echter de '++'. Na gebruik hiervan zal een -pointer naar het volgende element in het array wijzen, en in -een lus wordt dit zeer vaak gebruikt om de elementen een -voor een af te lopen. Dit is vaak handiger en bijna altijd -sneller dan met een index werken, al ziet het er voor niet -C-programmeurs soms wat onoverzichtelijk uit. - - -## S T R I N G S - -Tot nu toe is het een 'zware' aflevering geweest, maar -daaraan viel niet te ontkomen. Wees getroost: wie het tot nu -toe allemaal begrepen heeft zal de rest van de cursus ook -begrijpen. - -Strings in C zijn gelukkig heel simpel: het zijn gewoon -array's van het type char. De eerste letter van de string -vind je in element 0, de tweede in element 1, enzovoort. De -lengte van een string wordt dus nergens opgeslagen, in -plaats daarvan wordt na het laatste karakter een 0 -opgeslagen. Dit wordt een 'sentinel' (wachtpost) genoemd, en -zegt ons zoiets als: "Halt! Einde string." Dit houdt tevens -in dat we het array 1 groter moeten maken dan de maximum -lengte van de string, anders past het niet. - -Een andere consequentie is dat 0 nooit deel mag uitmaken van -de string, maar omdat strings eigenlijk bedoeld zijn voor -tekst is dit niet echt een probleem. - -In C kunnen we niet met hele array's (en dus ook strings) -tegelijk werken, in plaats daarvan gebruiken we pointers om -naar deze array's te verwijzen. De standaardbibliotheek kent -meer dan tien functie's die uitsluitend op strings -betrekking hebben, en strings kom je ook in veel I/O -routines tegen. In al die routines maakt men dus gebruik van -pointers, en de functie-return is meestal ook een pointer. - -## P R O G R A M M A V O O R B E E L D D E S O U N D E X C O D E - -In de Verenigde Staten zijn in de loop der tijden een groot -aantal volkstellingen gehouden, met het doel een beetje -overzicht te houden op de groeiende bevolking van dit land. -Vooral in het verleden was een groot percentage van de -mensen analfabeet, en veel mensen konden hun eigen naam -zelfs niet schrijven. - -Dit leidde ertoe dat ook de spelling van die namen niet -bekend was, en ambtenaren moesten vaak ter plekke zelf maar -verzinnen hoe een naam gespeld moest worden. Hierdoor waren -analfabeten vaak onder verschillende namen bij officiâle -instanties bekend. - -De ambtenaren van het volkstellingsbureau losten dit -probleem grotendeels op door voor namen een coderingsmethode -te verzinnen die voor namen met ongeveer dezelfde uitspraak -dezelfde code opleverde. Hierdoor was het mogelijk geworden -in bestanden namen te achterhalen zonder dat de precieze -spelling bekend hoefde te zijn. - -Deze coderingsmethode is vrij simpel, en laat zich -uitstekend tot een klein C-programmaatje maken. De -toepassingsmogelijkheden zijn legio, en is overal inzetbaar -waar we naar namen of woorden zoeken waarvan we de precieze -spelling niet kennen. - -De eerste letter van de code wordt gewoon uit de naam -overgenomen. Alle vorgende letters worden in klassen -verdeeld. Letters van klasse 0 (klinkers en bijna-klinkers) -worden genegeerd, andere klassen (1 t/m 6) worden gewoon als -nummer aan de code toegevoegd. Indien er twee of meer -letters van dezelfde klasse direkt achter elkaar staan, -wordt het nummer maar 1 keer toegevoegd. De totale code -wordt na vierde karakter afgekapt, of met nullen tot vier -karakters aangevuld. Om een voorbeeld te geven: zowel "jan" -als "johan" hebben de code "J500", "scheur" en "sguer" -hebben de code "S250". -``` - #include - - #define STRLEN 80 - - char naam[STRLEN]; - - char code[5]; - - char *soundex(src, dst) - char *src, *dst; - { - unsigned cur_len; - int alfa_pos; - char new_code, old_code, *old_dst; - - /* Onthoud begin van dst */ - old_dst = dst; - - cur_len = 0; - - /* Als string niet leeg is... */ - if (*src) { - - /* Neem eerste letter over */ - *dst++ = toupper(*src++); - cur_len++; - old_code = ' '; - - /* Doe tot codelengte = 4, of string ten einde */ - while (*src && (cur_len < 4)) { - - /* Bereken positie in het alfabet */ - alfa_pos = toupper(*src++) - 'A'; - - /* Als het een letter betreft, maak code */ - if ((alfa_pos >= 0) && (alfa_pos <= 25)) { - new_code="01230120022455012623010202"[alfa_pos]; - - /* indien code niet '0' en niet dubbel, voeg toe */ - if ((new_code != '0') && (new_code != old_code)) { - *dst++ = new_code; - cur_len++; - } /* if ((new_code... */ - old_code = new_code; - } /* if ((alfa_pos... */ - } /* while */ - } /* if (*src) */ - - /* Vul aan tot 4 karakters met '0' */ - while (++cur_len <= 4) *dst++ = '0'; - - /* Sluit de string af */ - *dst = '\0'; - - /* Geef originele pointer terug */ - return old_dst; - - } /* soundex */ - - main() - { - printf("\n\nBereken soundex-code\n\n"); - - while (TRUE) { - printf("Geef te coderen naam: "); - gets(naam, STRLEN); - - if ((*naam == '\n') (*naam == '\0') - (*naam == ' ')) - break; - - printf("\nDe soundex-code is: %s\n\n", - soundex(naam, code)); - } /* while */ - - printf("\n\nEinde programma\n\n"); - } -``` - -Na het doorlezen van bovenstaande listing zal menigeen met -een groot aantal vragen zitten. Laten we, net als de -computer, bij 'main' beginnen: - -Om te beginnen de - - while (TRUE) - -In "STDIO.H" wordt de constante TRUE ('waar') gedefinieerd. -Deze heeft in de meeste systemen de waarde 1, maar is in -ieder geval niet 0. De tegenhanger hiervan, FALSE -('onwaar'), is wel 0. Deze constanten worden gebruikt waar -we willen aangeven dat we logische waarden gebruiken. (In -tegenstelling tot PASCAL kent C geen speciaal logisch type.) -Deze constanten zijn alleen bedoeld om de leesbaarheid van -het programma te verbeteren. - -Betekent dit dat de 'while' lus eeuwig wordt doorlopen? Nou, -niet echt. In deze lus is gebruikt gemaakt van een -ontnappingsmogelijkheid die C ons biedt, namelijk het -'break' statement. Als dit wordt uitgevoerd springen we de -lus uit, naar het eerste statement na de lus. Deze 'break' -is ook in alle andere lussen bruikbaar. - -Dit 'break' statement is hier toegepast binnen een 'if' -statement. Hier kunnen we meteen zien hoe we met -karakterconstanten kunnen werken: gewoon tussen '' zetten. -Net als de strings die tussen "" staan kunnen we bijzondere -karakters aangeven met het escape-karakter '\' (backslash). -Ook hier betekent '\n' een newline, en met '\0' wordt de -ASCIIwaarde nul aangeduid. (Gewoon een 0 had ook gemogen, -maar zo is het duidelijker dat het een karakter betreft.) - -De vreemd uitziende '||' is een operator die staat voor -logisch-of (logical or). Als 1 van de afzonderlijke -uitdrukkingen niet-nul (ofwel logisch waar) is, is de hele -uitdrukking waar. We springen dus uit de lus als het eerste -karakter van het array 'naam' een spatie OF een newline OF -een nul is. Het bijzondere van de '||' vergeleken met de OR -uit BASIC of PASCAL, is dat er niet meer gerekend wordt dan -strikt noodzakelijk is: na de eerste deeluitdrukking (van -links gezien) die logisch waar is moet de hele uitdrukking -namelijk waar zijn, en hoeven we niet verder te rekenen. - -De tegenhanger van de logische-of is de logische-en (logical -and), die met '&&' wordt aangeduid. Hier echter is de -uitdrukking onwaar als 1 van de deeluitdrukkingen onwaar is. -Ook hiervoor geldt dat er zo min mogelijk wordt gerekend: -zodra een onware deeluitdrukking is gevonden, is de hele -uitdrukking onwaar, en stopt de berekening. Deze '&&' komen -we elders in het programma nog tegen! - -Even een stukje teruggaand zien we: - - gets(naam, STRLEN); - -STRLEN is een helemaal in het begin van het programma -gedefinieerde constante met de waarde 80. Hier is ook het -char array 'naam' gedeclareerd, met dezelfde lengte. De -standaardfunctie 'gets' leest een regel in van het -toetsenbord t/m de return, maar maximaal STRLEN-1 karakters, -omdat de tweede parameter de lengte van het array aangeeft. -Vervolgens wordt er nog een nul achtergeplakt, om het einde -van de string aan te geven. Als functie-return geeft 'gets' -de eerste parameter terug (een char pointer). In dit geval -doen we niets met deze functie-return. - -Na het 'if' statement staat tenslotte: - - printf("\nDe soundex-code is: %s\n\n", soundex(naam, code)); - -Hier zien we een nog onbekende format-specificatie, de '%s'. -Het zal niemand wel zeer verbazen dat dit voor 'string' -staat. De erbij behorende parameter moet naar een string -wijzen, een char pointer dus. De functie 'soundex' berekent -de soundex-code, en heeft als functie-return de waarde van -de tweede parameter, een char pointer. Op deze manier -pointers onveranderd teruggeven is heel gebruikelijk bij -string functies in C, zodat er meteen kan worden -doorgerekend. (Let wel: de pointer mag dan ongewijzigd zijn, -de string waarnaar die pointer wijst is dat natuurlijk -niet!) - -De functie 'soundex' berekent hier de soundex-code van de -string 'naam' en plaatst deze code in de string 'code'. -Natuurlijk moet 'code' dan wel voldoende ruimte bieden voor -de code, 'soundex' kan dit namelijk niet controleren. Terug- -bladerend naar het begin van het programma zien we dat het -array 'code' 5 char groot is, precies voldoende dus voor de -vier karakters en een afsluitende nul. - -Binnen 'soundex' zelf wordt - na de declaraties - eerst de -char pointer (dit korten we in het vervolg maar af tot: char -*) 'old_dst' gelijk gemaakt aan 'dst'. (Een afkorting van -'destination", oftewel 'bestemming'. Maar goed, "what's in a -name?") Dit moeten we doen omdat de pointer 'dst' veranderd -zal worden in de routine, en we willen de oorspronkelijke -waarde als functie-return gebruiken. - -Nadat 'cur_len' - het aantal codesymbolen tot nu toe - nul -is gemaakt, zien we: - - if (*src) { - -Met '*src' halen we het karakter op waar 'src' naar wijst. -Als dit karakter de waarde nul heeft is de string blijkbaar -leeg, en hoeft er niets gecodeerd te worden. Met - - *dst++ = toupper(*src++); - -wordt er 1 karakter van '*src' naar '*dst' gekopieerd, nadat -het tot hoofdletter is gemaakt. Ook worden beide pointer met -1 opgehoogd. Dat is nogal veel voor een enkel statement; zo -compact programmeren is typisch voor C. Laten we eens kijken -wat precies wat doet in dit statement. - -Om een van char - indien van toepassing - een hoofdletter te -maken is de standaarfunctie 'toupper' gebruikt. Deze heeft -een char parameter, en ook een char functie-return. - -Bij de '*dst++' en de '*src++' moet ik eerst wat over de -'++' operator vertellen: het maakt namelijk nogal wat uit of -de '++' voor of na de variabelenaam gebruikt wordt: in het -verleden waren we alleen geinteresseerd wat het effect was -op de variabele, en dat is in beide gevallen hetzelfde. De -waarde van de uitdrukking is echter heel anders: - - x = ++y; - -heeft hetzelfde effect als - - ++y; - x = y; - -en: - - x = y++; - -heeft hetzelfde effect als - - x = y; - ++y; - -Dus als we de '++' voor een variabelenaam gebruiken wordt de -waarde teruggegeven die de variable krijgt na het verhogen, -in het andere geval wordt de oude waarde teruggegeven (maar -de variabele wordt natuurlijk wel verhoogd!) Het statement - - *dst++ = toupper(*src++); - -heeft dus hetzelfde effect als - - *dst = toupper(*src); - ++dst; ++src; - -De eerste manier is natuurlijk bondiger en efficiânter, -hoewel niet echt begrijpelijker. De meeste C-programmeurs -zullen toch de korte methode kiezen. - -Even een technisch puntje: uit het bovenstaande blijkt dat -de operator '++' eerst wordt uitgevoerd, en daarna de '*'. -Je zou dus kunnen denken dat de '++' een hogere prioriteit -heeft dan de '*', maar dit is niet waar, ze hebben beide -dezelfde: alleen worden dit soort unaire operatoren van -rechts-naar-links uitgevoerd. Dit lijkt misschien onlogisch, -maar heeft meestal tot gevolg dat de unaire operator die het -dichtst bij de variabele staat het eerst wordt uitgevoerd. -Alleen het feit dat de '++' in bovenstaand voorbeeld achter -de variabele is gebruikt doet het wat onoverzichtelijk -lijken! - -Na dit statement komen we in een while-lus, die net zolang -doorlopen zal worden tot de lengte van de code-string 4 is, -of er geen karakters meer te coderen zijn. Het volgende -statement dat misschien enige uitleg behoeft is: - - alfa_pos = toupper(*src++) - 'A'; - -Hier zien we weer zo'n haal-en-ophoog constructie als -voorheen. Wat we echter ook zien is dat we met karakters net -zo kunnen rekenen als getallen! De variabele 'alfa_pos' is -van het int-type, en we zien dus ook dat dit soort -omzettingen door C automatisch worden gedaan. De variabele -'alfa_pos' bevat nu de plaats in het alfabet (van 0 t/m 25) -als het karakter een letter was. Zo niet, dan is 'alfa_pos' -kleiner dan 0 of groter dan 25. Door hierop te testen kunnen -we niet-letters negeren. - -De bij de positie in het alfabet behorende code wordt nu -berekend met: - - new_code = "01230120022455012623010202"[alfa_pos]; - -Ai! Dat ziet er vreemd uit, nietwaar? Een string met een -array-index erachter, hoe kan dat? Wel, zo vreemd is dat -niet. Op het moment dat C iets tussen "" tegenkomt zal deze -string ergens in het geheugen worden gezet (de afsluitende -nul wordt automatisch toegevoegd). In de expressie waarin de -string werd gevonden wordt met een char * naar deze string -verder gewerkt. En een pointer met een index erachter kan -natuurlijk zonder problemen worden gebruikt. Het resultaat -lijkt dus wat op de MID$-functie in BASIC, alleen wordt er -maar een enkel karakter uitgelicht, en tellen we vanaf 0. - -De het begrijpen van de rest van de functie mag nu weinig -problemen opleveren, vooral omdat er in commentaarregels -wordt aangegeven wat er gebeurt. - -Nog een laatste opmerking: bij het gebruik van lange -compound statements (tussen { }, remember?) na whileen -ifstatements e.d. is het een goede gewoonte om na het -afsluitende } een kort commentaar te gebuiken om aan te -geven bij welke 'while' of 'if' etc. het hoort. Ook het -telkens inspringen na 'while', 'if', etc. komt de -leesbaarheid zeer ten goede! Dat maakt het weer een stuk -gemakkelijker om fouten in het programma te vinden. Vooral -nietgepaarde { en } maken compilers vaak nogal, eh... -spraakzaam. - -Robert Amesz diff --git a/Sunrise Special/3/De programmeertaal C deel 4.md b/Sunrise Special/3/De programmeertaal C deel 4.md deleted file mode 100644 index 04cb18b..0000000 --- a/Sunrise Special/3/De programmeertaal C deel 4.md +++ /dev/null @@ -1,464 +0,0 @@ -# D E P R O G R A M M E E R T A A L C - D E E L V I E R - - - -## H E T F I L E S Y S T E E M V A N C - I N L E I D I N G - -De meeste programmeertalen stammen nog uit de tijd van de -teletypes en de grote mainframes. Alle informatie die de -computers toen konden tonen en verwerken bestond uit tekst -en getallen. Dit heeft grote invloed gehad op het -filesysteem van de huidige computers: deze zijn in principe -allemaal karakter- en byte-georiânteerd. Files worden gezien -als een rij achter elkaar staande karakters of bytes. Wat al -die bytes betekenen, en wat ermee gedaan moet worden mag de -gebruiker zelf beslissen. Vanuit C kun je files op twee -manieren benaderen: als binaire file en als tekstfile. - - -## F I L E - H A N D L E S E N F I L E - P O I N T E R S - -Wat enigszins verwarrend is, is het feit dat C eigenlijk -twee verschillende niveaus van fileroutines kent. Op het -laagste niveau wordt met "file handles" gewerkt, op het -andere met "file pointers". Beide benaderingen zijn totaal -verschillend, en kunnen niet zonder meer door elkaar worden -gebruikt. - -Het laagste niveau is het niveau van de "file handles". Dit -komt overeen met het laagste niveau zoals dat onder UNIX -gebruikt werd op de PDP11. (Daar is de taal C tenslotte voor -ontwikkeld.) De functies op dit niveau waren - voor zover ik -weet - gewoon routines van het operating system, die binnen -C gebruikt werden. - - -## F I L E H A N D L E S - -Een file handle is in feite niets anders dan een klein -geheel getal. Natuurlijk kan de gebruiker niet zelf dit -getal uitkiezen, dat doet het systeem op het moment dat een -bestand wordt geopend. Met deze file-handle kunnen we vanaf -dat moment bestanden lezen en schrijven, en het file -uiteindelijk sluiten. Op dit niveau kunnen we alleen een -(deel van een) bestand in een (zelfgekozen) buffer inlezen, -of vanuit een buffer naar een bestand schrijven. Ook de -grootte van de buffer is vrij te kiezen. - -Dit klinkt vrij primitief, en dat is het ook. Voor sommige -toepassingen is het echter voldoende, en de snelheid van -deze functies is een stuk hoger dan de meer uitgebreide, -maar daardoor meer gecompliceerde functies met file -pointers. Niet alle C-compilers kunnen met file handles -werken, en op deze manier met files werken komt vrij zelden -voor. Vandaar dat file handles hier nogal summier aan bod -zullen komen. - -Nvdr. Zie ook Sunrise Special #2, de MSX-DOS 2 cursus -behandelt ook file handles, en dit komt bijna overeen met de -file handles in C. - -## W E R K E N M E T F I L E H A N D L E S - -Het openen van een file gaat als volgt: - - open(naam, mode) - -Als parameters hebben we 'naam' (een char *) en 'mode' (een -int). De laatste moet de waarde 0 hebben als we een bestand -willen lezen, 1 om te schrijven, en 2 voor beide. Als het -openen gelukt is geeft de functie een file-handle terug, zo -niet dan ontstaat de waarde ERROR (ofwel -1). - -Lezen en schrijven kan met de functies: - - read(handle, buffer, aantal) - write(handle, buffer, aantal) - -De 'handle' moet de filehandle van een correct geopend -bestand zijn, 'buffer' een char * naar een blok geheugen, en -'aantal' de hoeveelheid bytes die we willen lezen of -schrijven. De functie geeft het daadwerkelijke aantal -gelezen of geschreven bytes terug, of -1 bij fouten. - -Na afloop sluiten we het bestand met: - - close(handle) - -Als alles goed ging krijgen we de waarde 0 terug, anders -1. - - -## F I L E P O I N T E R S - -File pointers zijn inderdaad pointers, maar waar ze precies -naar 'pointen' gaat alleen het filesysteem wat aan. File -pointers worden - net als file handles - bij het openen van -een file aan ons doorgegeven. Wij op onze beurt moeten de -file pointer weer gebruiken in alle functies die we bij dat -bestand willen gebruiken. - -Door files via file pointers te benaderen worden onze -mogelijkheden een stuk groter. Alle I/O functies lopen -intern via file pointers, ook bijvoorbeeld 'printf'. Met -file pointers kunnen we niet alleen lezen en schrijven van -en naar bestanden op schijf, maar kunnen we ook de in- en -uitvoerapparaten bereiken. We hoeven ook niet meer zelf onze -in- en uitvoerbuffers te kiezen, alles wordt verder door het -systeem geregeld. - -Buiten dat zijn er nog een drietal standaard "bestanden" -beschikbaar, die we niet hoeven (sterker nog: mogen) openen -of sluiten. Die aanhalingstekens staan daar omdat het in -feite invoer van het toetsenbord, en uitvoer naar het -beeldscherm betreft. Deze drie bestanden zijn: - -stdin oftewel: standaard invoer. Dit is gebufferde invoer - via het toetsenbord. Gebufferd betekent hier dat we - de gewone regeleditor gebruiken zoals onder DOS, en - dat pas na een return het eerste karakter - beschikbaar is. - -stdout oftewel: standaard uitvoer, het beeldscherm. - -stderr oftewel: standaard foutboodschap uitvoer, eveneens - het beeldscherm. - -Functies zoals 'printf' sturen al hun uitvoer naar 'stdout', -weer andere halen hun gegevens uit 'stdin'. Door de waarden -in 'stdin' of 'stdout' te vervangen door andere file -pointers kunnen we bijvoorbeeld zorgen dat 'printf' zijn -uitvoer op een ander apparaat doet. - - -## B I N A I R E F I L E S E N T E K S T F I L E S - -Bij het openen van een file moeten we niet alleen kiezen of -we willen lezen of schrijven (of beide) maar ook of het als -een binair of een tekstfile moet worden behandeld. Je kunt -je afvragen: waarom dit onderscheid? Tenslotte is het -onderscheid tussen een rij bytes en een rij 8-bit ASCII -karakters alleen een kwestie van interpretatie, en dat is -typisch een zaak voor de programmeur. Toch is er een -onderscheid, en dit hebben we te danken (wijten?) aan UNIX -en CP/M. - -De ASCII code is oorspronkelijk ontworpen voor gebruik met -teletypes, en uit die tijd stammen nog een groot aantal -controlecodes die we nog in de ASCII-tabellen aantreffen, -meestal met geheimzinnig aandoende drie-letterige -afkortingen, zoals SYN, SOH, EOT, enzovoort. Bij teletypes -zijn wagenterugloop (carriage return, kortweg CR) en -regelopvoer (line feed, kortweg LF) twee verschillende -acties, die dus ook allebei een eigen code hadden gekregen. -Voor een nieuwe regel moeten zowel een CR en een LF gebruikt -worden. In UNIX - die blijkbaar in de begintijd niet met -ASCII werkte - was voor die actie een enkele code, een -'newline' nodig (het karakter '\n'). - -Dit geeft problemen. C gaat uit van een enkele newline, waar -in onze ASCII files twee codes, een CR en LF staan. Oeps. -Hoe lost C dit op? Wel, bij het lezen van een CR en een LF -wordt maar een van de codes doorgegeven, gewoonlijk de LF, -en die wordt binnen de C-omgeving als newline gebruikt. -Omgekeerd wordt bij schrijven voor iedere newline een CR en -een LF geschreven. - -Het tweede probleem stamt uit de CP/M tijd, de voorloper van -zowel MSX-DOS als MS-DOS. CP/M werkt met records van 128 -byte elk, en de grootte van een file is alleen in records -bekend, en niet in bytes zoals in MSX-DOS en MS-DOS. De -consequentie daarvan is, is dat er na het laatste karakter -in een tekstfile nog maximaal 127 loze karakters konden -volgen. Lastig. Daarom werd er afgesproken dat als een -tekstfile het laatste 128 byte record niet exact wist te -vullen er een zgn. end-of-file karakter moest worden -geschreven, code 26 oftewel control-Z. Veel programma's -schreven zelfs altijd zo'n code als laatste karakter, of -rekenden erop dat die code altijd aanwezig was. (Een goede -kans: 127 tegen 1. Zulke programma's liepen niet vaak tegen -de lamp.) C houdt zich aan deze conventie, en geeft bij -tekstfiles een EOF zodra een control-Z wordt gelezen, of -schrijft een control-Z bij het sluiten ervan. - -## G E B R U I K V A N F I L E - P O I N T E R S - -In STDIO.H staat de typedefinitie van een file - die heet -FILE (met hoofdletters) - en filepointer variabelen kunnen -we declareren met bijvoorbeeld: - - FILE *een_file; - -Met de '*' geven we aan dat het een pointer-variabele -betreft. De variabele hebben we nodig om na het openen van -een file de filepointer te kunnen opslaan; tenslotte willen -we het bestand later nog kunnen lezen of schrijven, en -uiteindelijk sluiten, en voor al die acties is de -filepointer nodig. Het openen gaat als volgt: - - fopen(name, mode) - -De functie-return is van het type FILE *, en als het openen -mislukt krijgen we een NULL. Zowel "name" als "mode" zijn -van het type char *, en wijzen naar strings. Hierbij is -"name" de naam van het bestand en "mode" de manier waarop we -het bestand willen gebruiken, wat kan zijn: - -"r" tekstfile lezen ("read") -"w" tekstfile schrijven; wist het oude bestand. - ("write") -"a" als "w", maar voegt tekst toe aan het einde van een - bestand, en wist het oude bestand niet. ("append") - -Vaak kan lezen en schrijven worden gecombineerd: - -"r+" tekstfile lezen, maar ook schrijven -"w+" tekstfile schrijven, maar ook lezen -"a+" tekst toevoegen, maar ook lezen - -Voor binaire bestanden moet er nog een "b" worden -toegevoegd, en dan krijgen we "rb", "wb", "ab", "r+b", -enzovoort. - -Helaas kennen niet alle systemen alle manieren van lezen en -schrijven; een minimum is echter wel "r", "w", "rb" en "wb". - - - -## L E Z E N M E T F I L E P O I N T E R S - -Een typische manier om een bestand te openen in c is als -volgt: - - if ((een_file = fopen("help.txt", "r")) == NULL) { - printf("Helptekst niet op deze schijf!\n"); - return; } - -Hier onderbreken we dus de huidige functie op het moment dat -een bestand niet beschikbaar blijkt te zijn, en als het -bestand wel geopend kan worden is de filepointer meteen -opgeslagen in 'een_file'. Dit laat maar weer eens zien hoe -er in C zowel simpel, robuust als compact kan worden -geprogrammeerd. (Probeer hetzelfde maar eens in BASIC of -Pascal. Turbo Pascal wel te verstaan, want in standaard -Pascal is het al helemaal niet te doen.) - -Maar laten we ervan uitgaan dat het bestand geopend kon -worden. In dat geval kunnen we het file gaan lezen, en daar -zijn verschillende functies voor, zoals: - - getc(filepointer) - fgetc(filepointer) - fgets(buffer, aantal, filepointer) - -De functies 'getc' en 'fgetc' doen precies hetzelfde, al -zijn er - officieel tenminste - intern een paar verschillen. -Beide lezen een karakter van een file, en verwachten een -filepointer, voorgesteld door 'filepointer', als parameter. -Het karakter wordt - let goed op! - als int teruggegeven, -omdat de constante EOF (die we krijgen als we een karakter -proberen te lezen na het einde van het bestand) niet in een -char kan worden doorgegeven. - -De functie 'fgets' leest een hele regel tegelijk (dus t/m -'\n') in 'buffer' (een char *) maar nooit meer dan 'aantal' -- 1 karakters. Tevens wordt een afsluitende 0 toegevoegd. De -functie geeft de waarde 'buffer' terug, tenzij er een fout -is opgetreden, of voorbij het einde van het bestand wordt -getracht te lezen: dan krijgen we NULL. Let er wel op dat de -buffer voldoende groot is. Als er een char array gebruikt -wordt met tenminste 'aantal' elementen kan er niets fout -gaan. - -Omdat dit zo vaak voorkomt zijn er bovendien nog de twee -functies - - getchar() - gets(buffer, aantal) - -Deze zijn precies gelijk aan respectievelijk: - - getc(stdin) - fgets(buffer, aantal, stdin) - -Na afloop moeten we een file sluiten met - - fclose(filepointer) - -Ging alles goed dan krijgen we 0 terug, anders EOF. -Overigens zullen bij het beeindigen van een programma alle -nog open files automatisch gesloten worden. - - -## S C H R I J V E N M E T F I L E P O I N T E R S - -Voor het schrijven naar een file kunnen we van de volgende -functies gebruik maken: - - putc(karakter, filepointer) - fputc(karakter, filepointer) - fputs(string, filepointer) - fprintf(filepointer, ...) - -Met 'putc' of 'fputc' schrijven we een 'karakter' (een char) -naar een file. We krijgen EOF terug bij een fout, en anders -0. Darentegen schrijft 'fputs' alle karakters van 'string' -(een char *) tegelijk weg, met uitzondering van de -afsluitende 0. Bij deze functie krijgen we geen waarde -terug. Tenslotte 'fprintf' doet precies hetzelfde als -'printf', alleen schrijft deze functie naar een file. De ... -geven hier aan dat hier een lijst met parameters moet volgen -zoals bij 'printf'. Ook hier wordt geen waarde -teruggegeven.. - -De functies - - putchar(karakter) - puts(string) - -komen overeen met respectievelijk: - - putc(karakter, stdout) - fputs(string, stdout) - - -Ook na schrijven moet een bestand worden gesloten. - -Als laatste een functie die eigenlijk overal buitenvalt, -namelijk: - - unlink(filenaam) - -Hiermee kan een file 'filenaam' gewist worden. Deze functie -is zeer gevaarlijk, omdat (meestal) ook wildcards ('?' of -'*') zijn toegestaan, en een fout in het programma kan hier -wel heel vervelende gevolgen hebben. Bij succes wordt de -waarde 0 teruggegeven, anders -1. - -De naam 'unlink' is wederom een overblijfsel van Unix, die -op een wat andere manier met files omgaat. Met 'unlink' -wordt uit de directory van de huidige gebruiker de -referentie ('link') naar het file gehaald, en het file zelf -wordt pas gewist als alle referenties ernaar verdwenen zijn. - - -## 2 . 3 W A T N I E T A A N B O D K W A M . . . - -In de officiâle C-standaard bestaan nog een hoop andere -functies met files. Een aantal ervan (zoals 'seek' en -'tell') kunnen door de meeste C-compilers voor de Z80 niet -op de juiste wijze worden geãmplementeerd omdat het type -'long' ontbreekt. Andere functies ontbreken vanwege de -verschillen tussen UNIX en CP/M dan wel MSX-DOS. Sommige -ontbreken gewoon omdat men het blijkbaar niet de moeite -waard vond ze te programmeren. Voor microcomputers moet je -vaak een keuze maken, en de filesystemen nemen zonder meer -al het grootste deel van de standaardbibliotheken in beslag. -Wie meer wil weten moet de documentatie van de -desbetreffende compiler eens goed doorlezen. - - -## E E N V O O R B E E L D - - -Het aantal woorden in een file. - -Ook in deze aflevering een voorbeeldprogrammaatje. In -afwijking met voorgaande afleveringen is hier niet de hele -source opgenomen, maar alleen de belangrijkste functie. De -rest van het programma moet de lezer zelf maar eens -bestuderen; veel nieuws is er overigens niet in te vinden. - -Onderstaand programma zou vooral handig zijn geweest in de -hoogtijdagen van de Amerikaanse pulp-magazines. Vooral Isaac -Asimov - vorig jaar overleden - schroomde niet om in -heruitgaves van zijn oude verhalen precies te vertellen -hoeveel hem voor het publiceren van een bepaald verhaal -betaald werd, en hoe het bedrag werd berekend. - -De uitgevers betaalden namelijk per geschreven woord. -Afhankelijk van de kwaliteit van het verhaal en de -bekendheid en populariteit van de auteur lag dit bedrag -tussen de halve en twee dollarcent per woord. We praten hier -weliswaar over de dertiger en veertiger jaren, maar zelfs -dan is wel duidelijk dat de schrijverij voor de meesten niet -meer kon zijn dan een liefhebberij. Voor Asimov zelf duurde -het tot in de jaren vijftig voor hij full-time schrijver -werd, en tegen die tijd had hij al een carriäre als chemicus -achter de rug. - -``` - /* Tel de woorden. Geeft het aantal woorden in */ - /* een file. Als het file niet geopend kon */ - /* worden -1 */ - int telw(file_naam) - char *file_naam; - { - FILE *infile; /* File om uit te lezen */ - int teller; /* Lopend totaal */ - int karakter; /* Moet int zijn vanwege EOF */ - char inwoord; /* TRUE --> midden in een woord */ - - - if ((infile = fopen(file_naam, "r")) == NULL) - return -1; /* File kan niet geopend worden */ - - teller = 0; /* Geen woorden geteld */ - inwoord = FALSE; /* Start niet in woord */ - - /* Al 't werk gebeurt in dit while-statement */ - while ((karakter = getc(infile)) != EOF) - if (inwoord) - inwoord = ! leeg((char)karakter); - else - if (! leeg((char)karakter)) { - inwoord = TRUE; - teller++; } - - fclose(infile); - - return teller; - } -``` - -Allereerst wordt geprobeerd het file te openen, en als dat -mislukt wordt de waarde -1 teruggegeven. Daarna kan het -echte werk beginnen. - -De gebruikte methode is heel eenvoudig. De variabele -'inwoord' geeft aan of we midden in een woord zitten, of -erbuiten. Zodra we van buiten een woord in een woord komen -verhogen we 'teller' met 1. Na afloop bevat teller dan -precies het aantal woorden. - -Elders in het programma is de functie 'leeg' gedefinieerd, -die aangeeft of een karakter 'lege ruimte' voorstelt, zoals -een spatie, een newline, enzovoort. Een klein probleem hier -is dat de variabele 'karakter' van het type int is, en -'leeg' een char als parameter wil. Met '(char)' kunnen we -zo'n conversie afdwingen; dit wordt een 'cast' genoemd. Meer -hierover in de volgende aflevering. - -Het losse uitroepteken is de logisch-niet operator. Deze -geeft 0 (FALSE) als de uitdrukking erachter niet-0 (TRUE) -is, en omgekeerd. - -In de uitdrukking achter 'while' wordt 'getc' net zolang -aangeroepen tot een EOF gelezen wordt. Dit is een -gebruikelijke manier om een heel file te lezen. De variabele -'karakter' moet perse van het type 'int' zijn, omdat anders -de int-waarde automatisch naar een char wordt geconverteerd, -waarna er niet meer op EOF kan worden getest. - -Wie zich overigens afvraagt waarom er na de 'gets' (in -'main') zo ingewikkeld wordt gedaan, dit is omdat de newline -die na de aanroep van 'gets' in de string zit niet wordt -geaccepteerd als laatste karakter van een filenaam, en dan -zou het file niet geopend kunnen worden. Vandaar. - -Zo, dat was het dan weer voor deze keer. Zo langzamerhand -zal de lezer genoeg van C kennen om er al serieuze -programmaatjes in te kunnen schrijven. Dus hou vol, zelfs -als je denkt: "C is a harsh mistress!" - -Robert Amesz - \ No newline at end of file diff --git a/Sunrise Special/3/File handles.md b/Sunrise Special/3/File handles.md deleted file mode 100644 index 3cd4df3..0000000 --- a/Sunrise Special/3/File handles.md +++ /dev/null @@ -1,185 +0,0 @@ - -# F I L E H A N D L E S - - -In deel ÇÇn van de DOS2-cursus heb je kunnen zien wat File -Handles zijn. In deze tekst wordt duidelijk gemaakt hoe je -ze dient te gebruiken. Dit gaat aan de hand van een -voorbeeld-source om een file mee te kopiâren. - -Bij kopiâren komen de belangrijkste aspecten aan bod: -openen, aanmaken, lezen, schrijven en sluiten. - - -## M A C R O O T J E - -``` -AdrBDOS: EQU 5 ;Adres BDOS onder DOS - ;Is #F37D onder BASIC - -BDOS: MACRO @Func ;Macrootje - LD C,@Func - CALL AdrBDOS - ENDM -``` - -Deze macro maakt het voor mij iets makkelijker. Het scheelt -typewerk en het is duidelijk. Als je niet weet hoe macro's -werken, moet je de tekst daarover lezen op de vorige -Special. - - -## E Q U A T E S -``` -Open: EQU #43 ;File Handle openen -Create: EQU #44 ;File aanmaken en openen -Close: EQU #45 ;File Handle sluiten -Read: EQU #48 ;File Handle lezen -Write: EQU #49 ;File Handle schrijven -TermError: EQU #62 ;Terminate with errorcode -``` -Dit zijn de BDOS-functies die ik gebruik in deze source. - - - -## O P E N E N -``` - LD DE,Filename - LD A,%0001 ;No write - BDOS Open - JR NZ,Error - PUSH BC ;File Handle in B -``` -Met dit stukje source open je een File Handle. Functie 43H -werkt als volgt: - - Input: C = 43H (_OPEN) - DE = Drive/path/file in ASCIIZ - A = Open mode. b0 geset => niet schrijven - b1 geset => niet lezen - Output: A = Errorcode - B = Nieuwe File Handle - -Een ASCIIZ-string is een string die afgesloten wordt met -ASCII code 0 (Zero). Als er geen fout optreedt, is A 0. De -BDOS van DOS2 geeft zelf voor het terugkeren een OR A, dus -je hoeft dat zelf niet meer te doen. Je kunt meteen testen -op het Z bit, en evt. springen naar de error routine (zie -onderaan). - -B wordt hier gePUSHt, omdat B wordt gebruikt in de volgende -BDOS routine. B wordt weer gePOPt om de File Handle te -sluiten. Als je een File Handle de hele tijd (niet erg -exact, maar het is duidelijk) nodig hebt, kun je hem het -beste ergens in de buurt van de ASCIIZ string zetten. Mijn -favoriete stekje is de Zero byte, die je immers toch niet -meer gebruikt. - - -## L E Z E N -``` - LD DE,Buffer - LD HL,Length - BDOS Read - JR NZ,Error -``` - Input: C = 48H (_READ) - B = File Handle - DE = Buffer adres - HL = Aantal te lezen bytes - Output: A = Errorcode - HL = Aantal gelezen bytes - -De File Handle was nog goed. Length staat bij de string, -da's overzichtelijker. Buffer is gewoon de byte die volgt na -de laatste byte van het programma. Als je een grote file -inleest, moet je erop letten dat je niet over het hoogste -adres heengaat. Daar wordt later misschien nog op ingegaan -bij de bespreking van de Mapper Support Routines van DOS2. - -Een file van onbekende grootte moet je gewoon inlezen door -in HL een zo groot mogelijk (rekening houdend met hoogste -adres) getal in te vullen. Als de HL die terugkomt even -groot is als de input-HL, moet het lezen gewoon herhaald -worden. - - -## O V E R E N S L U I T E N -``` - POP BC ;File Handle terughalen - BDOS Close - JR NZ,Error -``` - Input: C = 45H (_CLOSE) - B = File Handle - Output: A = Errorcode - -Dit is niet noodzakelijk, maar wel netter. (Had ik maar zo'n -functie om de troep op mijn kamer op te ruimen...) - - -## C R E A T E -``` - LD DE,Filename - LD A,DestDrive - LD (DE),A - LD A,%0010 ;No read - LD B,0 ;File attributen - BDOS Create - JR NZ,Error - PUSH BC -``` -Eerst even het adres van de string inlezen, die vervolgens -aanpassen en de registers goed zetten. - - - Input: C = 44H (_CREATE) - DE = Drive/path/file in ASCIIZ - A = Open mode. b0 geset => niet schrijven - b1 geset => niet lezen - B = Gewenste attributen - Output: A = Errorcode - B = File Handle - - -## S C H R I J V E N -``` - LD DE,Buffer - LD HL,Length - BDOS Write -``` - Input: C = 49H (_WRITE) - B = File Handle - DE = Buffer adres - HL = Aantal te lezen bytes - Output: A = Errorcode - HL = Aantal gelezen bytes - - -## F O U T M E L D I N G E N -``` -Error: LD C,TermError - LD B,A ;Als A=0 dan geen error - JP AdrBDOS -``` -DOS2 heeft een hele mooie functie: Terminate with errorcode: - - Input: C = 62H (_TERM) - B = Errorcode - -Als B=0, komt er geen error op het scherm. Alle -foutmeldingen zijn (uiteraard) in DOS2-stijl. - -``` -DestDrive: EQU "H" -Filename: DB "A:\FILHANDL.GEN",0 -Length: EQU 1057 - -Buffer: END -``` -DestDrive is de bestemmingsdrive. De lengte moet kloppen met -de originele file. Als de lengte te groot is, krijg je "*** -End of file". - -Kasper Souren - \ No newline at end of file diff --git a/Sunrise Special/3/Getallen printen.md b/Sunrise Special/3/Getallen printen.md deleted file mode 100644 index 49843bd..0000000 --- a/Sunrise Special/3/Getallen printen.md +++ /dev/null @@ -1,213 +0,0 @@ - - G E T A L L E N P R I N T E N - - - Het komt bij programmeren vaak voor dat je getallen op het - scherm wilt zetten. In BASIC gaat dat meestal decimaal, dat - is in BASIC ook het makkelijkst. In ML is decimaal minder - makkelijk, binair of hexadecimaal is daar logischer. Ik zal - nu een drietal routines behandelen om in ML getallen - respectievelijk decimaal, hexadecimaal en binair op het - scherm te zetten. - - - D E C I M A A L - - Getallen in decimaal op het scherm zetten, in BASIC heel - makkelijk maar in ML toch iets moeilijker. Met onderstaande - routine kun je 16 bits getallen in ML decimaal printen met - voorloopnullen en naar keuze 1, 2, 3, 4 of 5 cijfers. - - De voorloopnullen zijn overigens niet gedaan voor de netheid - maar om de routine simpel te houden. In BASIC moet je moeite - doen om de voorloopnullen erbij te zetten, bij ML moet je - juist moeite doen om ze weg te laten. - - Tot zover de inleiding, laten we nu maar snel verdergaan met - de source. Zoals gewoonlijk staat de source op de disk als - ASCII file. - - - ; D E C I M A A L . A S C - ; Roep naar keuze DIGIT1, 2, 3, 4 of 5 aan voor uitvoer - ; met het gewenste aantal cijfers - ; In : HL=getal - ; Uit:Getal wordt met &HA2 op scherm gezet - ; Registers AF, DE, BC en HL worden gebruikt - ; Door Stefan Boer - ; (c) Ectry 1993 - ; Sunrise Special #3 - ; (c) Sunrise 1993 - - DIGIT5: LD DE,10000 - CALL PR_DIG - DIGIT4: LD DE,1000 - CALL PR_DIG - DIGIT3: LD DE,100 - CALL PR_DIG - DIGIT2: LD DE,10 - CALL PR_DIG - DIGIT1: LD DE,1 - CALL PR_DIG - RET - - - Door DIGIT5 aan te roepen wordt het getal met 5 cijfers - (digits) geprint, DIGIT4 met 4 cijfers, etc. De routine - PR_DIG (PRint DIGit) kijkt hoeveel maal DE in HL past, en - voert dat getal uit. - - - PR_DIG: XOR A ; teller = 0 - NEXT: LD B,H - LD C,L ; LD BC,HL - OR A ; wis carry, A blijft gelijk - SBC HL,DE ; trek DE van HL af - JR C,OUTPUT ; DE > HL, dan einde lus - INC A ; verhoog teller - JR NEXT - - - Eerst wordt het A register 0 gemaakt, dit is de teller die - bijhoudt hoe vaak DE in HL past. In de lus wordt eerst de - huidige waarde van HL bewaard in BC. PUSHen is hier niet - handig en het is sneller dan LD (...),HL. - - Vervolgens wordt DE van HL afgetrokken. SUB HL,DE bestaat - niet, dus moeten we SBC gebruiken en eerst de carry wissen - met OR A (anders zou een eventuele carry roet in het eten - kunnen gooien bij SBC, SuBtract with Carry). - - Treedt er nu een carry op, dan was DE blijkbaar groter dan - HL (past er dus 0 keer meer in) en verlaten we de lus. - Anders verhogen we de teller en doorlopen we de lus opnieuw. - - - OUTPUT: LD H,B - LD L,C ; LD HL,BC - ADD "0" - CALL &HA2 ; voer waarde uit - RET - - Hier wordt de waarde van HL voordat er de laatste keer werd - afgetrokken weer hersteld, dit is nodig om ook de andere - cijfers te kunnen afdrukken. Vervolgens wordt de ASCII code - van "0" bij A geteld (A bevat het aantal keren dat DE in HL - past), en wordt dit cijfer op het scherm gezet met BIOS - routine CHPUT (&HA2). - - Niet zo'n moeilijke routine, maar wel een handige die je - vaak nodig hebt. En er zijn toch veel beginnende - programmeurs die er moeite mee hebben. Hexadecimale uitvoer - is veel simpeler te programmeren, maar dat is voor de - gebruiker niet zo handig. Ik heb in ieder geval nog nooit - een spel gezien met de score in hexadecimaal! - - - H E X A D E C I M A A L - - De routine om hexadecimaal te printen is niet korter, maar - wel veel simpeler. Hexadecimaal wordt bijvoorbeeld vaak - gebruikt om adressen weer te geven. Genoeg gepraat, hier - komt de routine. De routine zet een getal in DE op het - scherm in 4 digits, met voorloopnullen. De routine is vrij - simpel, dus meer uitleg dan wat achter ; staat is overbodig. - - - ; H E X A M A A L . A S C - ; Print 16 bits getal hexadecimaal - ; In : DE = 16 bits getal - ; Uitvoer naar scherm - ; Gebruikt: AF, HL, BC - ; Door Stefan Boer - ; (c) Ectry 1993 - ; Sunrise Special #3 - ; (c) Sunrise 1993 - - PR_HEX: LD B,0 - LD A,D ; high byte - AND &HF0 ; linker digit - RRCA - RRCA - RRCA - RRCA ; verplaats naar lage nibble - CALL UITHEX ; uitvoer - LD A,D ; high byte - AND &H0F ; rechter digit - CALL UITHEX - LD A,E ; low byte - AND &HF0 ; linker digit - RRCA - RRCA - RRCA - RRCA - CALL UITHEX - LD A,E ; low byte - AND &H0F ; rechter digit - JP UITHEX ; CALL & RET - - UITHEX: LD HL,HEXTAB ; beginadres tabel - LD C,A ; LD BC,A (B was al 0) - ADD HL,BC ; bereken adres in tabel - LD A,(HL) ; haal ASCII code van digit - JP &HA2 ; CALL & RET - - HEXTAB: DM "0123456789ABCDEF" - - - B I N A I R - - Om het verhaal volledig te maken moet ook binair er nog bij, - al zul je dat normaal gesproken toch weinig gebruiken. De - routine is heel kort maar toch iets moeilijker te begrijpen - dan de routine voor hexadecimaal. - - De routine print het getal in C met 8 digits en voorloop- - nullen. Als je een 16 bits getal wilt printen, kun je de - routine natuurlijk gewoon twee keer aanroepen. Bijvoorbeeld: - - LD C,H - CALL PR_BIN - LD C,L - CALL PR_BIN - - Om HL 16 bits af te drukken. De source: - - - ; B I N A I R . A S C - ; Print 8 bits getal binair op het scherm - ; In: C = 8 bits getal - ; Uitvoer naar scherm - ; Gebruikt: - ; Door Stefan Boer - ; (c) Ectry 1993 - ; Sunrise Special #3 - ; (c) Sunrise 1993 - - PR_BIN: LD B,8 ; 8 bits te gaan - BINLUS: LD A,24 ; "0"/2 - RLC C ; roteer C, bit 7 naar carry - RLA ; roteer A, carry naar bit 0 - CALL &HA2 ; uitvoer - DJNZ BINLUS ; dit 8 keer - RET - - - Hier is denk ik nog wel wat uitleg nodig. In het A register - wordt eerst de waarde 24 gezet, dat is de ASCII code van "0" - (48), maar dan ÇÇn bit naar rechts geroteerd. Vervolgens - roteren we register C ÇÇn bit naar links, waarbij bit 7 (het - bit dat we willen afdrukken!) in de carry terecht komt. - Vervolgens roteren we register A ÇÇn bit naar links met RLA, - wat overigens hetzelfde is als RL A alleen sneller en een - byte minder. Hierdoor worden de bits die al in A stonden dus - meegeschoven, en staat de ASCII van "0" in A. Maar bij RL - wordt de carry in bit 0 geschoven. Was de carry 0, dan - gebeurt er niets en staat er "0" in A, was de carry 1, dan - wordt bit 0 gelijk en staat er "1"! Zo gaan we alle bits - langs. - - Kortom, het ziet er ingewikkeld uit maar is eigenlijk heel - simpel! - - Stefan Boer \ No newline at end of file diff --git a/Sunrise Special/3/Hybride Call Commando's.md b/Sunrise Special/3/Hybride Call Commando's.md deleted file mode 100644 index cbc29ec..0000000 --- a/Sunrise Special/3/Hybride Call Commando's.md +++ /dev/null @@ -1,567 +0,0 @@ - - HYBRIDE - - - C A L L - 1 - - - - In de serie Hybride artikelen hebben we het deze keer over - CALL commando's. Het CALL commando is aan MSX BASIC - toegevoegd om het mogelijk te maken uw eigen commando's of - toekomstige uitbreidingen te gebruiken. - - De syntax luidt: - - CALL [ (parameter,parameter ...) ] - - In plaats van CALL mag ook het onderstrepingsteken _ worden - gebruikt. - - Kennis van machinetaal is vereist voor het zelf maken van - een CALL commando. BASIC programmeurs kunnen de nieuwe - commando's natuurlijk wel zonder problemen gebruiken in hun - eigen programma's. - - Voordat we ingaan op het maken van een CALL commando wordt - er eerst enige achtergrondinformatie gegeven. - - - U I T B R E I D I N G S P A G I N A - - Een pagina is een stuk geheugen (ROM of RAM) van 16 kB. De - pagina's zijn genummerd van 0 t/m 3. - - Page: Adresbereik: - 0 &H0000-&H3FFF - 1 &H4000-&H7FFF - 2 &H8000-&HBFFF - 3 &HC000-&HFFFF - - De MSX computer heeft standaard pagina's met RAM, MAIN ROM - en Disk ROM. Daar kunnen echter door de fabrikant (in ROM - vorm) of door de gebruiker (in het RAM) uitbreidingspagina's - aan worden toegevoegd. - - Een uitbreidingspagina kan een machinetaalprogramma, een - apparaatuitbreiding, een BASIC-uitbreiding of een BASIC- - programma bevatten. De informatie daarover is opgeslagen in - SLTATR. SLTATR is een gedeelte van het systeemgebied, dat - begint op adres &HFCC9. Er is ÇÇn byte gereserveerd per - mogelijke pagina. Er zijn 4 primaire sloten mogelijk die elk - 4 secundaire sloten kunnen hebben. Elk slot bestaat weer uit - 4 pages, zodat SLTATR 4*4*4=64 bytes lang is. De bits van - de bytes in SLTATR hebben de volgende betekenis: - - Bit 7 BASIC programma (1=ja) - Bit 6 Apparaat uitbreiding (1=ja) - Bit 5 Statement uitbreiding (1=ja) (CALL commando) - Bit 4-0 Ongebruikt - - U kunt het adres dat bij een bepaalde pagina hoort berekenen - met de volgende formule: - - ADRES = &HFCC9 + 16 * primaire gleufnummer + 4 * secundaire - gleufnummer + paginanummer - - Voorbeeld: in uw computer zit het RAM in slot 3-2 en u heeft - een statement uitbreiding in page 1 gemaakt. Het adres wordt - dan: - - &HFCC9 + 16 * 3 + 4 * 2 + 1 = &HFD02 - - Bit 5 staat voor een statement uitbreiding, dus de waarde 32 - (2^5) moet naar adres &HFD02 worden geschreven: POKE &HFD02, - 32. De computer zal nu naar page 1 in slot 3-2 springen als - er een CALL commando wordt gegeven. - - - H E A D E R - - De eerste 16 bytes van een uitbreidingspagina worden samen - ook wel de header genoemd en zijn als volgt opgebouwd: - - Offset: Naam: Bevat: - ------------------------------------------------------------ - +0 ID "AB" - +2 INIT beginadr initialisatie - +4 STATEMENT beginadr statement uitbreiding - +6 DEVICE beginadr apparaat uitbreiding - +8 TEXT beginadr BASIC programma - +10 - 6 bytes gereserveerd - ------------------------------------------------------------ - - Aan het begin van een pagina moeten de letters "AB" (ASCII - &H41 en &H42) staan. De computer herkent daaraan de - uitbreidingspagina. Bij een RESET zal de computer zelf - kijken wat er in de pagina's staat en SLTATR overeenkomstig - invullen. Als u een CALL commando wilt gebruiken zonder een - RESET, dan zult u zelf in SLTATR moeten POKEn, zoals we bij - de uitleg van SLTATR al hebben gezien. - - - S T A T E M E N T U I T B R E I D I N G - - Wij interesseren ons nu alleen voor de statement - uitbreiding. Als er geen statement uitbreiding in de pagina - aanwezig is, moet STATEMENT gelijk zijn aan &H0000. Alleen - page 1 kan een statement uitbreiding bevatten. Er kunnen - problemen ontstaan als bij andere pagina's het veld - STATEMENT is ingevuld. - - Het is overigens logisch dat de statement uitbreiding in - page 1 moet staan. In page 0 staat de BIOS en in page 3 het - systeemgebied, dus die moeten ingeschakeld blijven. Het - BASIC programma staat in page 2 (als het een groot programma - is tot in page 3), dus page 1 is de enige mogelijkheid die - overblijft. - - Als de computer bij het uitvoeren van een BASIC programma - een CALL commando tegenkomt, wordt de naam van het commando - (het woord dat achter CALL staat) in PROCNM gezet. PROCNM - ligt in het systeem gebied, vanaf &HFD89. Alle kleine - letters worden omgezet in hoofdletters en de komma's worden - eruit gehaald (probeert u maar eens: _F,O,R,M,A,T het - werkt!). De naam mag 15 tekens lang zijn. Achter de naam - wordt een ASCII-teken 0 gezet. Daarna gaat de computer alle - pagina's langs die volgens SLTATR een statement uitbreiding - bevatten. - - Als de computer bij STATEMENT een waarde vindt die ongelijk - is aan &H0000, dan springt hij naar dat adres en laat de - besturing verder aan die routine over. De taak van de - routine is nu om te controleren of het het juiste statement - is. - - HL wijst naar het eerste teken na de naam van het CALL - statement in het tokenized BASIC. Spaties worden daarbij - niet meegeteld. Bij bijvoorbeeld CALL FORMAT wijst HL dus - naar de positie NA de T van FORMAT. - - Als de routine ziet dat het de juiste naam is, moet het - statement worden uitgevoerd en moet de routine worden - verlaten met de carry gereset (gelijk aan 0 dus). HL moet - naar het eerste teken na het commando wijzen (het einde van - de regel of een dubbele punt). Bij een CALL statement zonder - parameters is dat dus de oude situatie (bijvoorbeeld - _FORMAT), bij _COLOR(15,0) moet HL wijzen naar de positie - achter het tweede haakje. - - Is het een ander commando, dan moet de routine verlaten - worden met de carry geset (hoog) en HL onveranderd. De - andere registers mogen wel zijn veranderd. - - Samenvatting: - - - CALL statement wordt niet gevonden: verlaat routine met HL - onveranderd en carry hoog - - CALL statement is gevonden: voer CALL statement uit en - verlaat de routine met HL op de positie achter het gehele - CALL statement en de carry laag - - - S T A N D A A R D R O U T I N E - - Om het allemaal wat makkelijker te maken heb ik een - standaardroutine geschreven, die als CALL.ASC op de diskette - staat. U kunt deze routine gebruiken voor al uw CALL - statements. De routine kan ÇÇn, maar ook twee of meer - routines aansturen. Als al het RAM in ÇÇn slot zit (is - meestal zo), dan kunt u maar ÇÇn blok CALL commando's - tegelijk gebruiken. Er is dan namelijk maar ÇÇn page 1 - beschikbaar, en de statement uitbreiding moet altijd in page - 1 staan. - - Achter de standaardroutine staan drie voorbeelden van CALL - commando's, die u bij het maken van uw eigen blok CALL - commando's natuurlijk kunt weglaten. Ik ga deze routine - zometeen uitgebreid bespreken. Maar eerst even dit. - - - N A A R D I S K A S S E M B L E R E N - - Het is het makkelijkst als het blok CALL commando's met een - BLOAD,R kan worden geãnitialiseerd. De CALL code moet echter - op &H4000 staan, en daar kunnen we niet laden onder BASIC. - We moeten daarom twee ORGs gebruiken, ÇÇn voor het - intialisatieprogramma en ÇÇn voor de CALL code. Om het - allemaal toch netjes in ÇÇn .BIN file te krijgen moeten we - naar disk assembleren. - - Ik ga hier uit van WB-ASS2. GEN80 gebruikers zullen de - source dus enigszins moeten aanpassen. Je kunt met GEN80 - trouwens alleen maar naar disk assembleren. Bij WB-ASS2 kan - dit door de vragen die het ASM statement stelt als volgt te - beantwoorden: - - Listing afdrukken? Nee (Ja mag natuurlijk ook) - Ascii listing naar disk? Nee - Mcode in geheugen zetten? Nee - Mcode naar disk? Ja - Relocatie-tabel maken? Nee - - Vervolgens moet nog de filenaam worden ingetypt, - bijvoorbeeld CALL.BIN. WB-ASS2 gaat aan de slag en als - resultaat staat de file CALL.BIN op de diskette, die met - BLOAD"CALL.BIN",R kan worden gestart. - - (Nvdr. De tekst was langer dan 16 kB, u kunt het tweede - gedeelte in het submenu vinden.) - - - - - HYBRIDE - - - C A L L - 2 - - - - - Het is nu hoog tijd voor: - - D E S O U R C E - - ; CALL.ASC - ; Standaardroutine voor het maken van CALL commando's - ; Door Stefan Boer - ; (c) Ectry 1993 - ; Sunrise Special #3 - ; (c) Stichting Sunrise 1993 - - ; (Alleen) naar disk assembleren! - ; Resultaat starten met BLOAD"...",R - - ; Header voor .BIN file - - DEFB &HFE - DEFW EXEC - DEFW ENCALL-&H4001+STCALL - DEFW EXEC - - - Omdat we rechtstreeks een file aanmaken, moeten we zelf - zorgen voor de juiste header. Een BLOAD,R file moet beginnen - met een header van 7 bytes. De eerste byte is altijd &HFE, - hieraan kan een .BIN file worden herkend. Vervolgens 3*2 - bytes beginadres, eindadres en startadres. ENCALL is het - eindadres+1 van de CALL code die vanaf &H4000 staat. De - lengte van dat blok CALL code is dus ENCALL-&H4001. Om het - eindadres te berekenen wordt daar nog het eindadres van de - initialisatie routine bij opgeteld. - - ; Dit startadres moet eventueel omlaag als CALL code lang is - - ORG &HC000 - - ; Initialisatieroutine - ; Kopieer CALL code naar &H4000 - ; En zet bitje in SLTATR - - EXEC: LD A,(&HF342) ; slot RAM page 1 - LD H,&H40 ; PAGE 1 - CALL &H24 ; BIOS routine ENASLT - LD HL,STCALL - LD DE,&H4000 - LD BC,ENCALL-&H4000 - LDIR ; verplaats CALL code - LD A,(&HFCC0) ; slot MAIN ROM - LD H,&H40 - CALL &H24 - - - Hier wordt er RAM geselecteerd op adres &H4000, de CALL code - wordt gekopieerd en vervolgens wordt de MAIN ROM weer terug - gezet op adres &H4000. - - - LD HL,&HFCCA ; &HFCC9 + pagenummer (=1) - LD BC,&H10 - LD A,(&HF342) ; slot RAM page 1 - AND &B00000011 ; primair slotnummer - CLUS1: JR Z,CNEXT - ADD HL,BC ; tel primair*16 erbij op - DEC A - JR CLUS1 - CNEXT: LD BC,4 - LD A,(&HF342) ; slot RAM page 1 - AND A ; zet vlaggen goed - JP P,CEINDE ; is er wel secundair slot - AND &B00001100 ; secundaire gleuf * 4 - RRCA ; secundaire gleuf * 2 - RRCA ; secundaire gleuf - CLUS2: JR Z,CEINDE - ADD HL,BC ; tel secundair*4 erbij op - DEC A - JR CLUS2 - CEINDE: LD (HL),&H20 ; zet bit 5 aan - RET ; einde initialisatie - - - Hier wordt het juiste adres in SLTATR uitgerekend, en op dat - adres wordt de waarde &H20 gezet. Hieraan kan de interpreter - zien dat er een statement uitbreiding in die page zit. - - - STCALL: ; beginadres van code IN FILE - - - Als de BLOAD,R file is ingeladen, staat de CALL code niet op - adres &H4000 maar direct achter de RET van CEINDE. We hebben - dat adres nodig om de CALL code te kunnen verplaatsen en om - het eindadres uit te kunnen rekenen. Vandaar dit "loze" - label. - - - ; CALL code - - ORG &H4000 ; hier begint CALL code - - ; CALL header - - DEFM "AB" - DEFW 0 ; geen initialisatie - DEFW CAL ; startadres CALL code - DEFW 0 ; geen device - DEFW 0 ; geen BASIC - DEFW 0 - DEFW 0 - DEFW 0 - - - ; Hier springt interpreter naar toe bij CALL commando - - CAL: PUSH HL ; HL wijst naar teken na naam - van CALL statement - - ; Kijk of naam van CALL statement overeenkomt met - ; een van de namen in de tabel - - LD DE,TABEL ; begin van de tabel - C_1: LD HL,&HFD89 ; PROCNM bevat naam - LD A,(DE) ; lengte van naam - AND A ; zet vlaggen goed - JR Z,C_ERR ; einde tabel als A=0 - LD B,A ; lengte - INC DE - - C_2: LD A,(DE) ; vergelijk naam in tabel - CP (HL) ; met naam in PROCNM - JR NZ,NEXT1 ; naar NEXT1 als onjuist - INC DE ; volgende letter - INC HL - DJNZ C_2 - - LD A,(HL) ; laatste teken moet nu - AND A ; gelijk zijn aan 0, anders - JR NZ,NEXT2 ; is CALL naam te lang - - - Dit laatste stukje code is nodig om ervoor te zorgen dat het - verschil wordt gezien tussen bijvoorbeeld CALL SUN en CALL - SUNRISE. - - - ; alles Ok, spring naar CALL routine - - EX DE,HL ; HL is plaats in tabel - LD E,(HL) ; low byte sprongadres - INC HL - LD D,(HL) ; high byte sprongadres - EX DE,HL - JP (HL) ; spring naar dat adres - - ; Verkeerde naam, ga naar volgende naam in tabel - - NEXT1: LD C,B - LD B,0 ; BC=B - INC BC - INC BC - EX DE,HL - ADD HL,BC ; sla rest naam + sprongadres - EX DE,HL ; over - JR C_1 ; probeer het nog eens - - ; Naam te lang, ga naar volgende naam in tabel - - NEXT2: INC DE ; sla het sprongadres - INC DE ; over - JR C_1 ; probeer het nog eens - - ; Niet gevonden, einde routine met carry hoog - ; Als in andere sloten ook geen kloppend CALL commando - ; wordt gevonden, zal BASIC foutmelding geven - - C_ERR: POP HL - SCF ; Set Carry Flag - RET - - - Tot zover de "CALL handler". Het is in de code voor CALL - commando's makkelijk om een aantal routines uit de BASIC - interpreter "bij de hand te hebben": - - ; Handige routines - - ILLEGA: LD IX,&H475A ; Illegal function call - JP &H0159 - - SYNTAX: LD IX,&H4055 ; Syntax error - JP &H0159 - - R_BYTE: LD IX,&H521C ; Lees een byte van getokenized - JP &H0159 ; BASIC, resultaat in A - - R_WORD: LD IX,&H6F0B ; Lees een word van getokenized - JP &H0159 ; BASIC, resultaat in DE - - - Hier ontbreekt nog FRMEVL op adres &H4C64, waarmee elke - willekeurige expressie kan worden "geâvalueerd". De - interpreter zal VALTYP (&HF663) en DAC (&HF7F6) vullen met - het resultaat. De namen van de routines die door R_BYTE en - R_WORD worden aangeroepen zijn overigens respectievelijk - GETBYT en FRMQNT. - - - ; Tabel met CALL commando's - - TABEL: DB 4 ; lengte CALL commando - DM "INFO" ; de naam - DW INFO ; het adres - - DB 4 - DM "DSKI" - DW DSKI - - DB 6 - DM "KILBUF" - DW KILBUF - - DEFB 0 ; afsluiten - - - In deze tabel moeten alle namen, lengtes en startadressen - van de CALL statements in het blok CALL code worden gezet. - - Voor de duidelijkheid heb ik nog een drietal voorbeelden - toegevoegd. Op de disk staat de file CALLTEST.BIN, waarmee u - het zelf kunt uitproberen. - - - ; Voorbeelden - - ; CALL INFO - ; Zet melding op het scherm - - INFO: LD HL,TEXT ; begin tekst - INFO_1: LD A,(HL) ; ASCII teken - AND A - JR Z,INFO_2 ; klaar als 0 - CALL &HA2 ; teken naar scherm - INC HL - JR INFO_1 ; volgende teken - - INFO_2: POP HL ; pointer achter statement - XOR A ; wis carry: CALL commando Ok - RET - - TEXT: DM "Standaard CALL routine",13,10 - DM "(c) Ectry 1993",13,10,0 - - ; CALL DSKI (drive,sector,aantal,adres) - ; Lees sectoren in - - DSKI: POP HL ; pointer achter naam - - LD A,(HL) - CP "(" ; check haakje - JP NZ,SYNTAX - INC HL - - CALL R_BYTE ; haal drivenummer - LD (DRIVE),A - - LD A,(HL) - CP "," ; check komma - JP NZ,SYNTAX - INC HL - - CALL R_WORD ; haal start sector - LD (SECTOR),DE - - LD A,(HL) - CP "," ; check komma - JP NZ,SYNTAX - INC HL - - CALL R_BYTE ; haal aantal sectoren - LD (COUNT),A - AND A ; zet vlaggen goed - JP Z,ILLEGA ; Illegal function call als - ; 0 sectoren - - LD A,(HL) - CP "," - JP NZ,SYNTAX - INC HL - - CALL R_WORD ; haal adres (komt in DE) - - LD A,(HL) - CP ")" - JP NZ,SYNTAX - INC HL - - PUSH HL ; bewaar pointer - - LD C,&H1A ; BDOS call SETDMA - CALL &HF37D ; Zet DMA adres op DE - - LD DE,(SECTOR) ; DE=startsector - LD HL,(DRIVE) ; H=#sectoren, L=drive - LD C,&H2F ; BDOS call Absolute Disk Read - CALL &HF37D ; Lees sectoren - - POP HL ; pointer achter statement - XOR A ; wis carry: CALL commando Ok - RET - - ; data voor DSKI routine - - DRIVE: DB 0 - COUNT: DB 0 - SECTOR: DW 0 - - ; CALL KILBUF - ; Wis toetsenbordbuffer - - KILBUF: CALL &H0156 ; BIOS routine - POP HL ; pointer achter statement - XOR A ; wis carry: CALL commando Ok - RET - - ENCALL: END - - - Z E L F A A N D E S L A G - - Het zelf maken van een CALL commando is nu heel eenvoudig. - Schrijf een machinetaalroutine die u door een CALL commando - wilt laten aanroepen. U mag daarin de routines ILLEGA, - SYNTAX, R_BYTE en R_WORD gebruiken. Zorg dat bij het - verlaten van de routine HL wijst naar de positie na het - commando en dat de C vlag gewist is. Denk er verder om dat - de stack niet verandert ten opzichte van de situatie voordat - uw routine werd aangeroepen. - - Zet de standaardroutine erbij en zet het commando in de - tabel. De standaardroutine zorgt ervoor dat er alleen bij - het juiste CALL commando naar uw routine zal worden - gesprongen. - - Let erop dat het totale blok CALL commando's nooit meer kan - zijn dan 16 kB. Verlaag indien nodig de ORG &HC000. &H9000 - is in ieder geval altijd laag genoeg. U mag de BIOS routines - in page 0 en het systeem gebied in page 3 natuurlijk - gebruiken. - - Veel succes met het maken van uw eigen CALL commando's! - - Stefan Boer - \ No newline at end of file diff --git a/Sunrise Special/3/Memman problemen.md b/Sunrise Special/3/Memman problemen.md deleted file mode 100644 index 3cbfc2e..0000000 --- a/Sunrise Special/3/Memman problemen.md +++ /dev/null @@ -1,242 +0,0 @@ - M E M M A N - - I N T H E O R I E E N P R A K T I J K - - - I N L E I D I N G - - Onder MSX-DOS 1 laat het geheugenbeheer, met name bij - aanwezigheid van een memory mapper, veel te wensen over. Met - de komst van MSX-DOS 2 is dat sterk verbeterd, daar zitten - immers routines in om een pagina uit de memory mapper op te - roepen en weer vrij te geven. Volgens de deskundigen zit er - echter een bug in deze routines, waardoor eenmaal - opgevraagde pagina's nooit meer vrijgegeven kunnen worden, - tenzij de machine wordt gereset. - - Zo is MEMory MANager geboren. De programmeurs van MST hadden - de behoefte aan een stel goed werkende routines, waarmee het - gehele geheugen benut kan worden. Ze gingen echter verder. - Meerdere memory mappers, externe geheugen modules (16 & 64 - kB) en TSR's. Welnu over dit laatste onderwerp gaat dit - artikel. - - - W A T I S E E N T S R ? - - Gewoonlijk zal een programma na uitvoering niet in het - geheugen achterblijven. Programma's die dat wel doen, worden - aangeduid met de afkorting TSR: Terminate and Stay Resident. - Voorbeelden van dergelijke programma's zijn printerbuffers - en RAMdisks. Maar ook andere toepassingen, zoals een - rekenmachine of een kalender die met een toetscombinatie - opgeroepen kan worden, zijn denkbaar. - - In het verleden zijn TSR's voor de MSX een tamelijk zeldzaam - verschijnsel geweest. Het probleem was namelijk dat het - geheugen dat de TSR gebruikt, ook door andere programma's - gebruikt kan worden. Er zijn in een standaard MSX machine - geen mogelijkheden om een stuk geheugen voor een TSR te - reserveren. Dit probleem wordt door MemMan uit de wereld - geholpen. MemMan beheert het geheugen en zorgt er voor dat - er geen geheugenconflicten optreden. - - Dankzij MemMan is het mogelijk meerdere TSR's tegelijk in - het geheugen te hebben, waarbij elke TSR maximaal 16 kB - groot kan zijn. Op de standaard MSX is het laden van meer - dan ÇÇn TSR al lastig en alleen mogelijk als de TSR niet al - te groot is. Met de invoering MemMan krijgt de MSX betere - TSR mogelijkheden dan de alom gewaardeerde PC. Bovendien - doen ze niet onder voor de 'desktop accesoires' zoals die op - de Macintosh en de Atari ST gebruikt worden. - - Dit hoofdstuk is regelrecht overgenomen uit de handleiding - van MemMan, zoals die is geschreven door het MST. - - - N U D E P R A K T I J K - - Dat klinkt natuurlijk mooi, maar werkt het in de praktijk - ook zo soepel. Ik hoop in de rest van dit artikel een aantal - problemen boven water te halen, waaruit blijkt dat MemMan - heel leuk is, maar nog niet af. Daarentegen wil ik wel - iedereen blijven aanmoedigen om MemMan te blijven (of gaan) - gebruiken, want werken zonder MemMan is helemaal een gruwel. - - - P R O B L E E M 1 - - Een hoop bestaande programma's werken niet samen met MemMan - en profiteren dus niet van het bereikbaar worden van meer - geheugen. Bovendien werken veel programma's niet eens als - MemMan actief is. - - Het eerste gedeelte van het probleem is lastig op te lossen. - Het betekent dat ïf het programma herschreven moet worden, - ïf er moet een alternatief programma gebruikt worden, dat - wel met MemMan samenwerkt. - - Het tweede gedeelte van het probleem is veel leuker. Ook - hier herken je weer twee probleemgroepen. - - De eerste groep zijn de vastlopers. Als je je bedenkt dat - MemMan binnen de grenzen van de MSX standaard werkt, - betekent dit dat de vastlopende programma's dat dus niet - doen. Programma's die het gehele systeem voor zich opeisen - en denken dat ze ermee mogen doen wat ze willen. Helaas - bestaan ze. - - De tweede groep is het absolute toppunt voor m'n - lachspieren. Het programma geeft kort na het opstarten een - 'Not enough memory' error en het programma stopt. Het - probleem ligt hier in het TPA geheugen. - - Wat is TPA geheugen? Dat is de 64 kB die voor de processor - direct zichtbaar is. De rest van het geheugen is, net als - deze 64 kB, onderverdeeld in blokken van 16 kB. Door nu ÇÇn - van die blokken uit het TPA geheugen te verwisselen met een - blok uit de memory mapper, ziet de processor weer een ander - stukje data of programma. Om dit in goede banen te leiden is - MemMan ontwikkeld. Maar om goed te kunnen functioneren heeft - MemMan permanent een stukje geheugen nodig, zoals ook - MSXDOS(2).SYS en COMMAND(2).COM zich in dit geheugen - bevinden, maar ook de stack e.d.. Wat er nu nog overblijft, - is voor een in te laden programma en z'n te declareren - variabelen. Door MemMan is dat vrije TPA geheugen nu zo'n - 1,5 kB kleiner geworden. Voor sommige programma's genoeg - voor de eerder genoemde error. - - Dit laatste is alleen te verhelpen door het programma - opnieuw te compileren, met een verkleind vrij TPA geheugen. - Hiervoor heb je dan wel de source van het programma nodig en - dat is vaak een probleem. Als het om een commercieel pakket - gaat, is die source simpelweg onbereikbaar voor de - eindgebruiker. Het bedrijf wenst niet meer aan het programma - te sleutelen (veel voorkomend commentaar nu MSX commercieel - niet meer interessant is) en wil alleen voor grof geld de - source verkopen. Als het om een PD of shareware pakket gaat, - zou je de schrijver ervan kunnen benaderen met het eerder - genoemde verzoek. Sommigen zullen er gehoor aan geven - anderen niet. Persoonlijk vind ik dat elke programmeur hier - vooraf rekening mee moet houden en dus standaard met een - verkleind TPA geheugen moet compileren. - - Dit probleem is dus niet de schuld van de programmeurs van - MST. Programma's welke voor het MemMan tijdperk geschreven - zijn, kunnen moeilijk verweten worden dat ze niet met MemMan - samenwerken. Maar de overige moeilijkheden van dit probleem - zijn simpel te wijten aan het niet naleven van de standaard, - of het niet wensen rekening te houden met MemMan. Die - programmeurs welke in deze categorie thuis horen, zijn wat - mij betreft amateurs. - - Nvdr. Er is natuurlijk ook nog een categorie: programma's - waarvoor het samenwerken met MemMan onzin is. Bijv. spellen, - demo's en ook deze Special! Al zou de printerbuffer wel leuk - zijn bij het uitprinten. - - - P R O B L E E M 2 - - TSR's zijn vaak op te roepen d.m.v. een toetscombinatie. In - diverse programma's wordt ook gebruik gemaakt van een - toetscombinatie. Wanneer er een TSR actief is welke dezelfde - toetscombinatie gebruikt als een bepaalde functie uit het - lopende programma, heb je een probleem. Welke van de twee - wint nu het gevecht, het programma of de TSR. Oplossing - hiervoor is simpel. Toetscombinaties zijn voor TSR's. In een - normaal programma is het gebruik van toetscombinaties dus - uit den boze. - - Ook hier geldt hetzelfde als bij probleem 1. Programma's van - voor het MemMan en TSR tijdperk, kunnen dit niet verweten - worden. Maar programma's die ontwikkeld zijn toen MemMan en - TSR's wel reeds bestonden, hadden er rekening mee moeten - houden. De programmeurs van deze programma's zijn dus hier - egoãstisch bezig geweest. - - - P R O B L E E M 3 - - TSR's die elkaar in de haren vliegen, of de combinatie van - programma en TSR die elkaar niet liggen. Oorzaak: de al - eerder genoemde toetscombinaties, maar ook het actieve - SCREEN speelt een rol. Dit laatste punt heb ik lang over - nagedacht, maar ik denk dat hier, in tegenstelling tot de - andere moeilijkheden, een taak is weggelegd voor de - programmeurs van MemMan. - - Sommigen van jullie kennen ongetwijfeld de TSR Micro Music. - Deze TSR zet na een bepaalde toetscombinatie een menu op het - scherm. Welnu de programmeur heeft hier geen rekening - gehouden met het actieve screen en gaat er simpel vanuit dat - SCREEN 0 actief is. Gelukkig is hij niet de enige TSR - programmeur die deze fout maakt en het is dus ook geen - persoonlijke aanval op de programmeur van Micro Music. Deze - TSR wordt alleen als voorbeeld genomen. - - Maar ga eens in de positie van de programmeur staan. Eerst - uitzoeken welk SCREEN actief is, vervolgens kijken welk - gedeelte je daarvan wil gebruiken, dan de aanwezige info - ergens opslaan en de nieuwe info plaatsen. Bij het verlaten - van de TSR, moet dan de omgekeerde weg gevolgd worden. Als - je dan ook nog eens toevallig in een modem programma zit en - het scherm is constant aan verandering onderhevig, dan zijn - de rapen helemaal gaar. - - Het is dus veel eenvoudiger om te zeggen dat zo'n TSR alleen - werkzaam is in SCREEN 0. Sommige programmeurs kunnen dit - zelfs niet eens goed (Micro Music laat bij een actieve jANSI - een paar gekleurde blokjes zien boven in het scherm), maar - dat is een ander verhaal. MST zou hier kunnen helpen. - - Wanneer er in MemMan een routine zit, die voor TSR's een - universele manier aanbiedt voor het plaatsen van een - karakter op een op te geven positie op het scherm, ongeacht - welk SCREEN actief is en de oude informatie van die positie - bewaart, zijn we al een hele stap verder. Nu kan de - programmeur van een TSR simpel tegen MemMan zeggen: ik wil - dit karakter op die positie. Wanneer MemMan dan bijhoudt - welke posities gebruikt worden door de TSR, kan de - programmeur van de TSR voor het verlaten van de TSR deze - posities weer herstellen door aan MemMan de opdracht daartoe - te geven. - - De ideale oplossing voor bijna alle problemen. Veel - programma's wijzigen niets op het scherm, wanneer een TSR - actief is. Voor die gevallen dat zowel een programma als een - TSR actief zijn, die beiden het scherm geheel of - gedeeltelijk wijzigen, wordt het praktisch onmogelijk om dit - af te vangen. Die programma's die intensief met MemMan - samenwerken, zouden aan MemMan de door de TSR gebruikte - posities kunnen opvragen en deze dan niet gebruiken, maar - dat kan soms onoplosbare problemen met zich mee brengen. - Denk hierbij alleen maar aan de pulldown menu's e.d.. - - Dus de hier voorgestelde uitbreiding van MemMan is niet - alles dekkend, maar is een hele grote stap in de goede - richting. - - - C O N C L U S I E - - Wat is het leven met MemMan en speciaal hiervoor ontwikkelde - programma's toch een genot. Helaas laten diverse - programmeurs nog wel eens een steekje vallen. Wanneer ze de - inhoud van dit artikel nu eens als wet gaan beschouwen en - wanneer MST de voorgestelde uitbreiding van MemMan nu eens - bewerkstelligt, zijn we bijna waar we zijn moeten: - - Een systeem wat op een bijna optimale manier gebruik - maakt van alle mogelijkheden die het systeem bied. - - Tot slot nog ÇÇn extra opmerking voor de programmeurs. Wees - nu eens niet zo eigenwijs door er van uit te gaan dat de - aangesloten diskdrives A: en B: heten, maar vraag dit gewoon - aan het systeem. Harddisk gebruikers hebben A: en B: vaak in - gebruik als een partitie van de harddisk en de diskdrives - heten dan (in mijn geval) F: en G:. Maar het gebruik van - vele kopieerprogramma's is hierdoor niet meer mogelijk. - - Henk Hoogvliet - \ No newline at end of file diff --git a/Sunrise Special/3/Programmeren sample chip.md b/Sunrise Special/3/Programmeren sample chip.md deleted file mode 100644 index 7b11d53..0000000 --- a/Sunrise Special/3/Programmeren sample chip.md +++ /dev/null @@ -1,176 +0,0 @@ - P R O G R A M M E R E N S A M P L E C H I P - - - In deze tekst ga ik beschijven hoe je samples gemakkelijk in - BASIC of ML kunt gebruiken. Deze chip zit in de Music Module - van Philips, omgebouwde Toshiba modules en de standaard - MSX-AUDIO cartridges van Panasonic. - - - O U T C 0 H E N O U T C 1 H - - Met deze twee OUT's wordt de hele MSX-AUDIO bestuurd. Door - een getal op poort &HC0 te zetten kies je een register en - door op poort &HC1 een getal te zetten stuur je dat getal - naar het eerder gekozen register. - - - Een overzicht van de registers: - - Register 1: Niet gebruiken - - Register 2: Timer 1 preset. Beginwaarde N1 van Timer 1. - - Register 3: Timer 2 preset. Beginwaarde N2 van Timer 2. - - Register 4: Timer en Flag control. - Bit 0: "1" starten en "2" stoppen Timer 1. - Bit 1: "1" starten en "2" stoppen Timer 2. - Bit 2: niet in gebruik. - Bit 3: "1" maskeert Buffer Ready Flag. - Bit 4: "1" maskeert End of Sample Flag. - Bit 5: "1" maskeert Timer 2 Flag. - Bit 6: "1" maskeert Timer 1 Flag. - Bit 7: "1" reset alle Flags. - Bij het inschakelen van dit register worden bit 3 en 4 al - gemaskeerd. Bij het invoeren van de waarde &H78 in dit - register worden alle Flags gemaskeerd en bij het invoeren - van &H80 worden alle Flags gereset behalve de al eerder - gemaskeerde Flags. Voor meer informatie zie het Status - register. - - Register 7: ADPCM besturing. - Bit 0: "1" reset ADPCM functies. - Bit 1, 2, 3: niet in gebruik. - Bit 4: "1" herhaalt weergave sample. - Bit 5: "1" voor gebruik geheugen in module. - Bit 6: "1" opnemen en "0" weergeven. - Bit 7: "1" start opnemen of weergeven. - Bij invoeren van &HE0 kan er worden opgenomen en met &HA0 - weergegeven. Met "1" worden alle bits gereset. - - Register 8: Instellingen - Bit 0: Moet altijd op "0" worden gezet. - Bit 1: Moet altijd op "0" worden gezet. - Bit 2: "1" DA en "0" AD conversie. - Bit 3: "1" start en "0" stopt DA/AD conversie. - Bit 4, 5, 6: niet in gebruik. - Bit 7: "1" stelt CSM in. - Indien ADPCM mode gewenst is moeten alle bits "0" zijn. - - Registers 9 en 10: Startadres Sample. - Er is standaard 256 kB in blokjes van 32 kB RAM om te - samplen. Dus zijn er 256/32 = 8 van &H2000 bytes. De - adressen lopen dus van &H0000 tot &H1FFF. Als er een - geheugenuitbreiding aanwezig is, bijv. 1024 kB en er wordt - gesampled met een goed prgramma dat ook die 1024 kB gebruikt - zijn er 1024/32 = 32 van &H8000. De adressen lopen dan van - &H0000 tot &H7FFF. In register 9 komt de low-byte en in - register 10 komt de high-byte. Dus als het beginadres &H03FF - is dan zet je in register 9 &HFF en in register 10 &H03. - - Registers 11 en 12: eindadres. - Zie registers 9 en 10 alleen nu voor het eindadres. Bij 32 - kB is dat &H1FFF. In register 11 komt de low-byte en in - register 12 komt de high-byte. - - Registers 13 en 14: prescaler. - In deze registers komt een getal N te staan waarmee de - samplefrequentie Fs wordt bepaald door de klokfequentie van - 3580 kHz te delen door N. De maximale samplefrequentie is 16 - kHz en de minimale samplefrequentie is 1.8 kHz. - - Opname Frequentie | N | Register 13 | Register 14 - -------------------+-----------+--------------+------------- - 1.8 kHz | &H7FF | &HFF | 7 - 3 kHz | &H4A9 | &HA9 | 4 - 6 kHz | &H254 | &H54 | 2 - 10 kHz | &H166 | &H66 | 1 - 16 kHz | &H0E1 | &HE1 | 0 - ------------------------------------------------------------ - - Register 15: ADPCM-data. - Dit register is een buffer voor de ADPCM data van en naar de - computer. Dit register kan geschreven en gelezen worden. - Elke byte bevat 2 ADPCM samples die maar 4 bits (ÇÇn nibble) - bevatten. Als de high-nibble sample nummer "n" bevat dan - bevat de low-nibble het sample nummer "N+1" - - Registers 16 en 17: ADPCM weergave. - Deze registers bevatten de snelheid van de ADPCM weergave, - oftewel de afspeelfrequentie. - - Weergave frequentie | register 16 | register 17 - ----------------------+-----------------+------------------- - 1.8 kHz | &HF4 | &H08 - 3 kHz | &H5D | &H0F - 6 kHz | &HBA | &H1E - 10 kHz | &H36 | &H33 - 16 kHz | &HF0 | &H51 - 50 kHz | &HFF | &HFF - ------------------------------------------------------------ - - Register 18: volume weergave ADPCM. - Met dit register kan het volume van de weergave van de ADPCM - worden ingesteld. Met &HFF staat het volume voluit en met - &H00 is het geluid op zijn zachtst. Dit register kan goed - gebruikt worden voor fade ins en outs. - - Registers 19 en 20: ADPCM. - Deze twee registers bevatten de ADPCM-codering en - -decodering. - - Registers 24 en 25: Output control. - Met deze registers kan het geluid aan- en uitgezet worden. - In register moet altijd "8" staan om outputpoort 3 te - kiezen. Wanneer in register 25 het getal "8" wordt gezet - gaat het geluid aan en wanneer er "0" wordt gezet gaat het - geluid uit. - - Register 26: PCM-data. - Bufferregister voor AD en DA conversie, de data wordt hierin - opgeslagen in 2-complement vorm. - - - H E T S T A T U S R E G I S T E R - - Dit register kan gelezen worden zonder dat er eerst een - register moet worden aangeroepen. - - Bit 0: dit bit is "1" tijdens ADPCM opname/weergave. - Bit 1 en 2: zijn niet in gebruik en staan op "1". - Bit 3: deze Flag wordt op "1" gezet als de - datatransport klaar is. - Bit 4: Als het opnemen of afspelen klaar is wordt - dit bit gezet. - Bit 5: Gezet als Timer 2 "0" is. - Bit 6: Gezet als Timer 1 "0" is. - Bit 7: Dit bit wordt gezet als bits 3, 4, 5 en 6 - gezet zijn, er wordt dan een interrupt - veroorzaakt. De computer kan dan zien of de - interrupt veroorzaakt werd door de - soundprocessor. - - - H E T I N V O E R E N - - Dan nu hoe je al deze registers kunt programmeren. Zoals ik - al eerder heb geschreven doe je dit met OUT &HC0,register en - met OUT &HC1,waarde die naar het register moet. - - Dus als je het volume voluit wilt zetten doe je: - OUT &HC0,18:OUT &HC1,&HFF - - Zelf sample ik het liefst in MoonBlaster en daarna schrijf - ik die sample(s) weg om ze vervolgens in BASIC in te laden - met de MB BASIC routines. - - Nu begrijp je misschien waarom het makkelijk is de sample(s) - aan te kunnen sturen. Veel mensen die alleen de een sample - aan willen sturen maken een songfile waarbij ze dan precies - timen wanneer zo'n sample afgespeeld moet worden. In het - softwaremenu staat een programma om samples op te nemen en - af te spelen. - - Bart Schouten - \ No newline at end of file diff --git a/Sunrise Special/3/Scrollen in kun basic.md b/Sunrise Special/3/Scrollen in kun basic.md deleted file mode 100644 index b1c5a63..0000000 --- a/Sunrise Special/3/Scrollen in kun basic.md +++ /dev/null @@ -1,72 +0,0 @@ - S C R O L L I N G I N K U N - B A S I C - - - Zo, nu gaan we weer eens terug naar het begin: BASIC! Ik heb - namelijk een horizontale scroll gemaakt, geheel an al in - BASIC geschreven! Geen bitje machinetaal! (Nou ja, die ene - sprong naar adres &H69 niet meegerekend, dat is om eventueel - aanwezige sprites te wissen. Die routine staat gewoon in het - BIOS.) Het enige wat je nodig hebt is KUN-BASIC, oftewel - XBASIC. - - Kijk maar eens in de listing hoe ik het precies gedaan heb. - De truuk is: VDP(19) en het gebruik maken van integer - variabelen. - - - V D P R E G I S T E R 1 8 - - Zo! Hier ben ik nog eens met wat aanvullende info over de - super-scroll in BASIC. Zoals eerder vermeld heb ik gebruik - gemaakt van VDP register 18 (VDP(19)) Dit register wordt ook - gebruikt met het commando SET ADJUST (X,Y). Het is ook - mogelijk om met dit register verticaal te scrollen, maar dat - zou niet slim zijn, want met register 18 kun je dan over - slechts 16 pixels scrollen. vdp register 23 (VDP(23)) is dan - een beter alternatief, omdat dat register, nou ja, laat ik - maar zeggen, speciaal gemaakt is om verticaal te scrollen: - alle 8 bits worden gebruikt voor die ene richting: - verticaal. Je kunt zo dus heel eenvoudig en snel verticaal - scrollen, over 255 beeldlijnen (ja! Onder het scherm zit - namelijk ook nog het gedeelte waar de sprites, kleurwaardes - e.d. opgeslagen zijn, maar die zie je normaal niet). - Voorbeeld in de listing ALPHA.BAS in de laatste regels. - - Nu even terug naar register 20. Zoals gezegd worden 4 bits - voor de verticale en 4 bits voor de horizontale - positionering gebruikt. Scrollen bestaat dus eigenlijk uit: - 1 keer per interrupt 1 pixel "opschuiven" en in de tijd dat - je zo 16 pixels laat opschuiven, ÇÇn keer het hele - beeldscherm m.b.v. het COPY-commando kopieert. Et voilÖ! Een - mooie horizontale scroll! - - - P R O B L E E M P J E - - Nou is er nog een probleempje met de ietwat vreemde - programmering van het register: als je netjes 16 pixels wilt - scrollen, moet je eerst de waardes 8 t/m 15 invoeren, en - daarna pas 0 t/m 7, anders klopt er niet zoveel van. - - Zo, dat was het wel, ik hoop dat BASIC-programmeurs en ook - wel ML-programmeurs in spÇ hiermee wel vooruit kunnen. Voor - voorbeelden kijk je maar in de listing. - - Och, voor ik het vergeet: ik gebruikte wel het woord - interrupt, maar daarmee bedoel ik de tijd die de VDP nodig - heeft om een beeld op te bouwen, normaal dus 1/50 seconde - (of 1/60 bij Japanse computers). Om mooi die tijd aan te - houden, gebruik ik de TIME variabele, deze wordt namelijk - door de VDP met een opgehoogd, als de VDP klaar is met het - opbouwen van een beeld, dus elke 1/50 seconde. - - Volgende keer heb ik misschien een mooi programma (in - BASIC!) om zelf vector-graphics te maken. Een programma - waarmee je in principe elk willekeurig 3-dimensionaal object - kunt invoeren, en dan in elke richting kunt laten draaien, - verplaatsen, vergroten e.d. Lijnen die dan (gedeeltelijk) - buiten het beeld vallen worden geclipt: ze worden dan toch - goed getekend!! - - Randy Simons - \ No newline at end of file diff --git a/Sunrise Special/3/TSR Change CPU.md b/Sunrise Special/3/TSR Change CPU.md deleted file mode 100644 index 3f36587..0000000 --- a/Sunrise Special/3/TSR Change CPU.md +++ /dev/null @@ -1,236 +0,0 @@ - - C H A N G E C P U 2 - - - Naar aanleiding van de bespreking van de TSR Development Kit - volgt hier uitleg bij een source van een TSR. - - - N A A M G E V I N G - - TsrName: MACRO - DB "Ntm CHGCPU 2" - ENDM - - Deze TSR heb ik CHGCPU 2 genoemd omdat CHGCPU al bestond. - Met dat programma - van Ramon van der Winkel - kun je van - processormode wisselen met de HAI en IIE toetsen die naast - de spatiebalk zitten. Mijn programma gebruikt echter het - schakelaartje naast reset, dat verder alleen bij het - opstarten wordt gebruikt. - - Het is gebruikelijk om de initialen van je naam op de eerste - drie of vier plaatsen te zetten. Ntm is een afkorting voor - Nuthemagic (ja, nieuwe naam bedacht). - - De tekst moet overigens PRECIES 12 karakters lang zijn, - anders kom je voor onherkenbare problemen te staan. Ik kwam - er zelf pas achter toen ik de handleiding van het pakket had - doorgelezen. Iets dat ik meestal pas doe als ik een - programma doorheb. - - - M E M M A N - F U N K T I E - - MemMan: MACRO @FNC - LD E,@FNC - CALL #4002 - ENDM - - Bij MemMan 2.42 is er de mogelijkheid bijgekomen om in een - TSR op naar adres #4002 te springen, i.p.v. het adres op te - vragen via een tijdrovende Extended BIOS CALL. - - - DB "MST TSR",13,10 ;TSR identifier - TsrName ;ID-Name - DB 26 ;End Of File - DW 0002 ;Header file versie, - ; MemMan 2.2 in dit - ; geval - DW Base ;Code base address - DW Init ;Init address - DW Kill ;Kill address - DW Talk ;TsrCall entry - DW TsrLen ;Programma code - ; lengte - DW IniLen ;Init code lengte - - Hierboven staan de verschillende adressen die voor TsrLoad - nodig zijn om de TSR goed in te kunnen laden. - - - T S R - C O D E Z E L F - - Hier volgt het programma zelf. Base is de eerste byte van de - code die in het geheugen moet blijven staan. Het - Init-gedeelte wordt namelijk verwijderd na gebruik. (Erg - milieuvriendelijk is het niet, hergebruik zou best mogelijk - zijn.) - - Base: ;Eerste byte code - Kill: ;Geen kill-routine - Talk: RET ;Geen driver-routine - - Program: EX AF,AF' ;Hier begint het - ; echte werk - - EX AF,AF' is noodzakelijk omdat register A na de CALL van - H.TIMI (#FD9F) nog wordt gebruikt door de BIOS. EX AF,AF' is - hier makkelijker dan PUSH en POP omdat je in register A' een - code voor de TSR afhandelingsroutine van MemMan mee kunt - geven: EndHook. Dan worden de TSR's die verder nog aan de - hook hangen niet meer aangeroepen. - - - LD A,5 - OUT (#E4),A ;Zet op ISS-read - IN A,(#E5) ;Read ISS-stand - AND #40 ;Alleen bit 5 - - Zie MSX-Mozaãk voor uitgebreide informatie over de - OUT-poorten van de turbo R. In ieder geval staat er nu #40 - in A als de schakelaar naar links staat en #00 als de - schakelaar rechts staat. - - - LD HL,SaveByte ;Vergelijk met oude - CP (HL) ; stand - JR Z,EndProgram ;Gelijk? Niks doen - LD (HL),A ;Bewaar nieuwe stand - - Als de oude stand gelijk is aan de nieuwe, wordt er naar het - einde van de hookverwerking gesprongen. Werken met HL is - hier handiger dan de waarde in een ander register zetten en - dan daarmee vergelijken. - - - XOR #40 ;Precies andersom - RLA ;Schuif bit naar - RLA ; goede plaats - RLA ;Eentje minder voor - RLA ; R800-ROM - OR #80 ;LEDje wisselen - - Hier wordt de accumulator even goedgezet voor CHGCPU van de - BIOS. Als je wilt dat er naar R800-ROM en niet naar - R800-DRAM moet worden geschakeld, moet je ÇÇn RLA weglaten. - Indien je prefereert dat de schakelaar rechts de Z80-mode - aanduidt, moet je XOR #40 weglaten. Als je dit zelf niet - kunt omdat je de TSR Development Kit niet hebt, kun je - natuurlijk altijd naar de postbus schrijven, dan zal ik het - wel doen en je de juiste TSR opsturen. - - - LD IX,#0180 ;CHGCPU - LD IY,(#FCC0) ;BIOS-slot in IYH - CALL #001C ;CALSLT - - Interslot call naar CHGCPU routine van BIOS. Zou zonder - problemen een gewone CALL kunnen zijn, maar ik vind dit - gewoon veiliger. - - - EndProgram: XOR A - EX AF,AF' - RET - SaveByte: DB 0 - - TsrLen: EQU $-Base - - XOR A is nodig om de flags voor de TSR afhandelingsroutine - van MemMan goed te zetten. EX AF,AF' zet de flags op de - juiste plaats en herstelt ook weer de accumulator voor de - BIOS. - - SaveByte is vervolgens een byte om de huidige stand in te - bewaren. TsrLen geeft de lengte aan van de echte TSR-code. - - - I N I T I A L I S A T I E - - Init: LD HL,tTsrName ;Pointer naar naam - MemMan 62 ;Get TSR ID: - JR NC,InitError ;Ja, print tekstje - - Als de naam al bestaat is de carry laag en wordt er dus naar - de error-routine gesprongen. - - - LD A,(#FCC1) ;BIOS-slot in A - LD HL,#2D ;MSXTYP - CALL #0C ;RDSLT - CP 3 ;Kleiner dan 3? - JR C,InitError ;Ja, print tekstje - - Hier wordt even getest of de computer wel een turbo R (of - hoger?) is. Zo nee, dan wordt er naar de error-routine - gesprongen. - - - LD A,%10 ;Beâindig met tekst - LD DE,tInit ;Pointer naar tekst - RET ;Terug naar TsrLoad - - Geef flags mee in A en pointer naar tekst als bit 1 gezet is - in register DE. - - - InitError: LD A,%11 ;Fout, met tekst - LD DE,NoTRTekst - RET C ;Turbo R fout? - LD DE,tDouble - RET - - Als de computer naar InitError springt omdat de TSR al in - het geheugen zit is de carry laag. Als de betreffende - computer geen turbo R is, is de carry hoog. Hiervan maak ik - gebruik om een zo kort mogelijk stukje code te krijgen. - - - tTsrName: TsrName - - tInit: DB 12,"Wissel tussen R800-DRAM-mode en " - DB "Z80-mode d.m.v. de schakelaar naast" - DB " de resetknop",13,10,10 - DB "Freeware, Nuthemagic 11/10/92" - DB 13,10,10,0 - - NoTRTekst: DB "Helaas, pindakaas, dit werkt alleen" - DB " op een turbo R.",13,10,10,0 - - tDouble: DB "Twee keer dezelfde " - DB "TSR installeren heeft geen zin!" - DB 13,10,10,0 - - IniLen EQU $-Init ;Lengte init-code - - De diverse teksten. IniLen is om de initialisatiecode te - verwijderen. - - - H O O K - T A B E L - - Hooks: DW HokTabLen - DW #FD9F ;Hook - DW Program ;Code horende bij - ; hook - HokTabLen: EQU $-Hooks ;Lengte van - ; hook-tabel - - Met de hook-tabel kun je aangeven welke hooks je wilt - afbuigen. Dit gaat dus echt heel erg simpel. - - De lengte van de hook-tabel wordt bepaald door van het - huidige adres ($) het beginadres van de hook-tabel af te - trekken. - - De source is alleen nuttig ter leringh ende vermaeck. - Slechts als je de TSR Development Kit koopt kun je de TSR - daadwerkelijk veranderen. Zie de betreffende tekst daarover - voor meer informatie. - - Uiteraard staat de TSR wel op deze disk. Veel plezier ermee! - - Kasper Souren - \ No newline at end of file diff --git a/Sunrise Special/3/TSR Development kit.md b/Sunrise Special/3/TSR Development kit.md deleted file mode 100644 index 45d595f..0000000 --- a/Sunrise Special/3/TSR Development kit.md +++ /dev/null @@ -1,91 +0,0 @@ - - - MEMMAN - - - T S R D E V E L O P M E N T K I T - - - Producent : MSX Software Team - Computer : - M S X 2 (80 kB RAM) - Medium : 1 dubbelzijdige diskette - Leverancier: MCM's lezersservice - - - Een tijdje geleden alweer dat dit produkt voor het eerst - verkocht werd. Zolang geleden zelfs dat ik toen nog geen ML - kende. - Maar hier volgt alsnog de bespreking van dit MST-produkt. - - - H E T P A K K E T - - ...bestaat uit een handleiding en een disk. Veel tekst uit - de handleiding zullen de meeste kopers van het pakket al - hebben: documentatie van MemMan calls en het artikel over - interrupts dat al in MCM heeft gestaan. Nieuw zijn echter de - beschrijving van het maken van TSR's volgens de MemMan - standaard - toevallig het belangrijkste - en de sources van - de PB.TSR en PRINT.COM. - - - D I S K - - Op de diskette staat eveneens een groot aantal files die al - in het bezit zijn van potentiâle kopers. Alleen LT.COM, de - linker, en daardoor het belangrijkste stukje bitvolgorde op - deze disk, en de raamwerken voor TSR-listings voor M80 en - GEN80. Ook zijn er nog 2 batchfiles, maar dat mag niet - bijster interessant worden genoemd. - - Wat je op deze disk mist zijn de 2 sources die wel in de - handleiding staan geprint. Misschien is dit gedaan ter - voorkoming van het vrijkomen van versies met hele kleine - aanpassingen. - - - R E L - B E S T A N D E N - - De linker werkt alleen met relocatable files. Files die op - een door de gebruiker of een ander programma dan de - assembler op de juiste plaats te zetten zijn. Beschrijving - van deze REL-files is te vinden op Sunrise Special #1. - - Voor zover ik weet is het alleen met GEN80 en M80 mogelijk - om REL-files aan te maken. Bij M80 is het trouwens alleen - maar mogelijk om REL-files te produceren. WB-ASS2 gebruikers - worden hierdoor uitgesloten, maar dit is niet zo erg: GEN80 - is toch veel beter! - - De linker maakt van die REL-files TSR-files. Deze files zijn - mijns inziens gewoon veredelde REL-files. In zoverre - veredeld dat TsrLoad ze makkelijk in een MemMan segment kan - plaatsen. - - - Z E L F M A K E N - - Zelf een TSR maken is een koud kunstje met dit LinkTsr. In - je source geef je de hook(s) aan die wilt afbuigen en zet je - de code die aan die hook(s) komt te hangen. Je hoeft je - verder dus niet te bekommeren over het vrijmaken van ruimte - in de top van het geheugen en het correct afbuigen van de - hooks. - - Als voorbeeld staan CHGCPU2.TSR en VOLINMET.TSR met source - en uitleg op deze Special. - - - C O N C L U S I E - - Als je dit koopt moet je niet denken dat je iets nieuws in - handen krijgt. Het grote voordeel is dat je nu alles bij - elkaar hebt, in ÇÇn handleiding. Als je makkelijk TSR's wilt - maken, is het zeker aan te raden! Maar ook als je al je - eigen systeem hebt om TSR's te maken is het een aanrader: - het is wel zo leuk voor de gebruikers om een eigen versie Çn - een MemMan versie te verspreiden. - - Waarschuwing: alleen voor GEN80- en M80-gebruikers. - - Kasper Souren - \ No newline at end of file diff --git a/Sunrise Special/3/TSR Volume Input Meter.md b/Sunrise Special/3/TSR Volume Input Meter.md deleted file mode 100644 index 7136bd1..0000000 --- a/Sunrise Special/3/TSR Volume Input Meter.md +++ /dev/null @@ -1,316 +0,0 @@ - - MEMMAN - - - V O L U M E I N P U T M E T E R - - - Naar aanleiding van de bespreking van de TSR Development Kit - volgt hier uitleg bij een source van een TSR. Het is beter - om eerst de tekst over CHGCPU2.TSR te lezen, want in deze - tekst ga ik er vanuit dat die tekst al gelezen is. - - - N A A M G E V I N G - - TsrName: MACRO - DB "Ntm VolInMet" - ENDM - - VolInMet is de afkorting voor Volume Input Meter. Deze TSR - gebruikt de PCM input om de 5 LED'jes als meter te - misbruiken. Ntm is uiteraard van Nuthemagic. - - - B E G I N V A N S O U R C E - - MemMan: MACRO @FNC ;Macro voor MemMan - LD E,@FNC ; funkties - CALL MemManEntry - ENDM - - DB "MST TSR",13,10 ;TSR identifier - TsrName ;ID-Name - DB 26 ;^Z - DW 0002 ;Header file versie - ; MemMan 2.2 in dit - ; geval - DW Base ;Code base adres - DW Init ;Init adres - DW Kill ;Kill adres - DW Talk ;TsrCall entry - DW TsrLen ;Programma code - ; lengte - DW IniLen ;Init code lengte - - - Base: EQU $ ;Eerste byte van - ; programma - - Dit hele stuk is al uitgelegd in de andere tekst. - - - K I L L - C O D E - - Kill: LD A,(CAPS) ;Lees voormalige - ; stand van CAPS in - OUT (#AA),A ;en zet het weer - ; goed - - LD A,15 ;Lees KANA stand in - OUT (#A0),A ; en herstel - LD A,(KANA) - OUT (#A1),A - - LD A,(R800nPAUSE) ;Herstel R800- en - LD (#FCB1),A ; PAUSE LED'jes - OUT (#A7),A - - CALL Drive_off ;Drive-LED'je uit - LD A,(Sound) - OUT (#A5),A - Talk: RET ;Geen driver routine - ; (Waarom twee keer - ; RET als ÇÇn keer - ; genoeg is?) - - - Bij de initialisatie-routine wordt de huidige stand van de - LED'jes ingelezen, en de LED'jes worden weer goed gezet bij - het verwijderen van de TSR. - - Een driver routine is niet nodig, dus daar staat gewoon RET. - - - H O O K - V E R W E R K I N G - - Program: PUSH AF ;Bewaar AF - CALL Sample ;Neem monster, - ; output in A - CALL ChangeLEDs ;Verander LED's - ; aan de hand van de - ; waarde in A - XOR A ;MemMan TSR handler: - EX AF,AF' ; doorgaan met hook- - POP AF ; verwerking - RET - - Lekker duidelijk programmeren! Er zullen wel geen vragen - ontstaan over bovenstaand stukje. - - - S U B R O U T I N E S - - ChangeLEDs: SUB 50 ;A kleiner dan 50? - JR C,Caps_off ;CAPS e.v. uit - - 50 aftrekken van A, als A kleiner is dan 50, ontstaat er een - carry en wordt alle LED'jes (te beginnen bij CAPS) uitgezet. - Ik gebruik in dit geval CP omdat de routines dan duidelijker - zijn, er staat nu overal SUB 50, i.p.v. CP 50, 100, 150 enz. - - - Caps_on: EX AF,AF' ;A veiligstellen - IN A,(#AA) ;Alleen CAPS-bitje - AND 191 ; aanpassen - OUT (#AA),A - EX AF,AF' - SUB 50 ;A kleiner dan 100? - JR C,Kana_off ;KANA e.v. uitzetten - - Kana_on: EX AF,AF' ;A bewaren - LD A,15 ;KANA LED'je - OUT (#A0),A ; aanzetten - IN A,(#A1) - AND 127 - OUT (#A1),A - EX AF,AF' - SUB 50 ;A kleiner dan 150? - JR C,Pause_off ;PAUSE e.v. uit - - Pause_on: EX AF,AF' ;A bewaren - LD HL,#FCB1 ;In HL is - ; makkelijker - LD A,(HL) ;In (#FCB1) staat - ; stand van PAUSE - ; en R800 LED - OR 1 ;PAUSE aan - LD (HL),A ;Terugzetten - OUT (#A7),A - EX AF,AF' - SUB 50 ;A kleiner dan 200? - JR C,R800_off - - R800_on: EX AF,AF' - LD A,(HL) ;HL is nog #FCB1 - OR 128 ;Idem, wel met R800 - LD (HL),A ; LED - OUT (#A7),A - EX AF,AF' - SUB 50 ;A kleiner dan 250? - JR C,Drive_off - - Drive_on: LD E,#14 ;Drive LED'je aan- - LD A,#8B ; zetten d.m.v. - LD HL,#7FF2 ; klooien in drive- - JP #0014 ; controller - ;Met dank aan Mr. X - ; (kweenie meer wie) - - Waarde #14 in slot 3.2 (#8B) op adres #7FF2 zetten. JP komt - i.p.v. CALL en RET. - - - Caps_off: IN A,(#AA) ;CAPS uit - OR 64 - OUT (#AA),A - - Kana_off: LD A,15 ;KANA uit - OUT (#A0),A - IN A,(#A1) - OR 128 - OUT (#A1),A - - Pause_off: LD HL,#FCB1 ;PAUSE uit - LD A,(HL) - AND 254 - LD (HL),A - OUT (#A7),A - - R800_off: LD A,(HL) ;R800 uit, HL - AND 127 ; staat nog goed! - LD (HL),A - OUT (#A7),A - - Drive_off: LD E,#04 ;Drive uit - LD A,#8B - LD HL,#7FF2 - JP #0014 - - Sample: LD B,250 - LD D,B - LD A,12 ;Opnemen - OUT (#A5),A - LD A,128+120 ;Grens - LD (#A4),A - - Startwaarde wordt op 250 gezet. Telkens als er een "aan" - binnenkomt, wordt dat getal met ÇÇn verminderd. - - - Sample_loop: IN A,(#A5) - AND #80 ;Bit 7 gezet? - JR NZ,Count ;Nee, dan aftrekken - DJNZ Sample_loop - LD A,D - RET - - Count: DEC D - DJNZ Sample_loop - LD A,D - RET - - CAPS: DB 0 ;Bytes om voormalige - KANA: DB 0 ; stand LED'jes in - R800nPAUSE: DB 0 ; te bewaren - Sound: DB 0 - - - MemManEntry: JP 0 ;Ingevuld door init. - - TsrLen EQU $-Base ;Lengte van TSR - - - I N I T I A L I S A T I E - - Init: LD A,(#FCC1) ;BIOS-slot - LD HL,(#002D) ;MSX-type - CALL #0C ;Readslot - CP 3 ;turbo R? - JR C,Error ;Nee he? Toch geen - ; simpele computer? - - Eerst bepalen of het wel een turbo R is. Hopelijk hebben de - toekomstige versies (al komen die er volgens mij nooit) ook - dezelfde LED'jes, die op dezelfde manier aangestuurd worden. - :-) - - - IN A,(#A5) - LD (Sound),A - IN A,(#AA) ;CAPS aan? - LD (CAPS),A - LD A,15 - OUT (#A0),A ;KANA aan? - IN A,(#A1) - LD (KANA),A - LD A,(#FCB1) - LD (R800nPAUSE),A - - Stand van LED'jes bewaren. - - - LD B,6 ;MemMan entry - ; opvragen - LD DE,256*'M' + 50 ;MemMan info funktie - CALL #FFCA ;via extended BIOS - ; hook - - LD (MemManEntry+1),HL ;Bewaar MemMan - ; entry - - LD HL,tTsrName ;Pointer naar TSR - ; naam - MemMan 62 ;TSR al aanwezig? - JR NC,Error - - LD A,%10 ;Tekstje printen - LD DE,tIntro ;Tekstpointer in DE - RET ;Terug naar TsrLoad - - Error: LD DE,tDouble - LD A,%11 ;Init mislukt, toch - ; tekst afbeelden - RET NC - - LD DE,tIntro - LD A,7 ;Ook introtekst - LD (tNoTurboR-1),A ; printen - RET - - Zelfde foefje als bij CHGCPU2. - - - tTsrName: TsrName ;Macro, zie boven - - tIntro: DB 12 - DB "Volume Input Meter",13,10 - DB "------------------",13,10,10 - DB "Misbruikt de 5 LED'jes van de MSX " - DB "turbo R als meter van het geluid!" - DB 13,10,10 - DB "Freeware door Nuthemagic op een" - DB " kille donderdagmiddag, 10 december " - DB "1992, luisterend naar een opname van " - DB "Rave Radio.",13,10,10 - DB "Mochten er vragen of opmerkingen zijn:" - DB 13,10 - DB "Sunrise BBS Nuth, 045-245910, 24 uur " - DB "per dag.",13,10,10,10 - DB 0 - tNoTurboR: DB "Minstens ÇÇn turbo R benodigd om deze" - DB " TSR te draaien.",13,10 - DB 13,10,10,10,0 - - tDouble: DB "Jammer, maar 2 keer laden lukt echt " - DB "niet, hoor.",13,10,10,0 - - IniLen: EQU $-Init ;Length of init-code - - Hooks: DW HokTabLen ;Lengte van - ; hook-tabel - DW #FD9F ;Hook - DW Program ;Programma aan hook - - HokTabLen: EQU $-Hooks ;Lengte van tabel - - Kasper Souren - \ No newline at end of file diff --git a/Sunrise Special/3/Turbo Pascal Patch.md b/Sunrise Special/3/Turbo Pascal Patch.md deleted file mode 100644 index 9f9463c..0000000 --- a/Sunrise Special/3/Turbo Pascal Patch.md +++ /dev/null @@ -1,76 +0,0 @@ - T P A T C H 1 . 1 - - - Nieuw in deze versie: aanpassing heap adres - - TPATCH patcht Turbo Pascal 3.0A MSX programma's automatisch - voor het gebruik met de MST Memory Manager. MemMan TSR's - functioneren alleen correct als de stackpointer in RAM - pagina 3 staat. Turbo Pascal zet echter zelf een lokale - stack op, waarbij de stackpointer in pagina 1 of 0 terecht - kan komen. Dat kan tot een crash leiden. - - Het is weliswaar mogelijk met een debugger het - stackpointer-adres in TP-programma's aan te passen, maar dat - neemt veel tijd in beslag. Daarom is TPATCH geschreven. - TPATCH zet de stackpointer van het TP-programma automatisch - op het default adres (0C500H in de distributie-versie) of op - een adres dat als parameter in de commandline opgegeven is. - Versie 1.1 van TPATCH past bovendien de heap-pointer aan. - - - Turbo Pascal deelt programma's als volgt in: - - 00100H Start runtime - 020EAH Start programma - 0xxxxH Ruimte voor stack & heap - 0yyyyH Start data - 0zzzzH Eindadres programma - - Na het gebruik van TPATCH ziet de indeling er als volgt uit: - - 00100H Start runtime - 020EAH Start programma - 0xxxxH Loze ruimte (zo klein mogelijk houden) - 0yyyyH Start data - 0zzzzH Eindadres programma - 0zzzzH+1 Ruimte voor stack & heap - 0ssssH Opgegeven top van de stack - - - Doordat het heap-adres in de vorige versie niet werd - veranderd, gaf de MAXAVAIL functie verkeerde resultaten. Die - functie geeft namelijk het verschil weer tussen de adressen - waar stackpointer en heappointer zich bevinden. Wordt de - stackpointer BOVEN het programmagedeelte geplaatst, dan ziet - MAXAVAIL veel meer ruimte dan er is, en kan programmacode - overschreven worden. - - De ruimte die voorheen voor heap en stack gereserveerd werd, - dient nu zo klein mogelijk gemaakt te worden, door in het - compiler-Options menu van Turbo Pascal het eindadres zo laag - mogelijk te zetten (zodat nog nät geen memory overflow - ontstaat). Een bijkomend voordeel is dat de uiteindelijke - COM-file die Turbo Pascal aanmaakt kleiner wordt. - - Houd er bij het programmeren verder rekening mee, dat de - heap en stack voldoende ruimte moeten hebben. Maak - programma's niet te groot. Overlays gebruiken extra - heapruimte. - - - Het gebruik van TPATCH: - - TPATCH FILENAAM[.COM] [hhhh] - - Vul voor de hhhh het (hexadecimale) adres in waar de - stackpointer op moet komen te staan. Wordt alleen de - filenaam opgegeven, dan zet TPATCH de stackpointer op $C500. - Die zgn. 'default' waarde is aan te passen door met een - debugger of disk-editor (eenmalig) het programma TPATCH.COM - aan te passen. Op de adressen $102 en $103 (START+2 en - START+3) staat nu: 00 C5, zijnde $C500 in hexadecimale - notatie (LSB,MSB). Dat kan naar believen veranderd worden. - - Pierre Gielen - \ No newline at end of file diff --git a/Sunrise Special/3/Turbo-R systeemcounter.md b/Sunrise Special/3/Turbo-R systeemcounter.md deleted file mode 100644 index 128a427..0000000 --- a/Sunrise Special/3/Turbo-R systeemcounter.md +++ /dev/null @@ -1,153 +0,0 @@ - T U R B O R S Y S T E E M C O U N T E R - - - Beloofd is beloofd, ik zou nog een tekst schrijven over de - systeemcounter van de turbo R. - - - W A A R O M E E N C O U N T E R ? - - Waarom hebben de ontwerpers van de turbo R er een counter in - gezet? Het is bij software vaak nodig om zo nauwkeurig - mogelijk tijdsduren te kunnen meten. Bijvoorbeeld om iets te - timen. Bij de Z80 werd hiervoor gewoon de verwerkings- - snelheid van de Z80 zelf gebruikt. Bij de Z80 staat het - namelijk van elke instructie vast hoe lang de Z80 erover - doet, zodat je precies kunt uitrekenen hoe lang het - uitvoeren van een bepaald stukje code duurt. - - Bij de R800 is dat anders, zie het artikel op Sunrise - Special #1. De R800 wordt bijvoorbeeld sneller als alles - zich binnen dezelfde 256 bytes afspeelt, en bovendien is de - refresh anders geregeld. Bij de Z80 wordt er na elke - instructie een refresh gedaan, bij de R800 is dat 32 keer - per seconde. - - Door dit alles is tijdmeting op basis van klokpulsen bij de - R800 niet nauwkeurig. Vandaar dat er een systeemcounter in - is gezet. - - - 1 6 B I T S - - De systeemcounter is eigenlijk heel simpel, gewoon een 16 - bits tellertje dat op twee I/O poorten zit en hardwarematig - wordt verhoogd (dus onafhankelijk van of bijv. de interrupts - aan of uit staan, of er wordt geladen van disk, etc.). - - De frequentie van de counter, en dus van de low byte, is - precies ÇÇn veertiende deel van de snelheid van de Z80A - (3.58 MHz), ofwel 255682 Hz. De counter wordt dus elke 3.91 - microseconde (miljoenste seconde) verhoogd. - - De high byte loopt uiteraard op 1/256 van deze snelheid, dat - is 999 Hz. De high byte heeft dus een frequentie van - ongeveer 1 kHz. - - - I / O P O O R T E N - - De counter zit op de I/O poorten &HE6 en &HE7, waarbij &HE6 - de low byte is en &HE7 de high byte. Voor gebruik in BASIC - zijn deze counters gewoonweg te snel, maar voor gebruik in - ML zijn ze uitermate geschikt. - - De counter kan worden gereset (op 0 gezet) door een - willekeurige waarde te schrijven naar poort &HE6. Schrijven - naar poort &HE7 heeft geen enkele invloed. - - Beide poorten kunnen worden gelezen. Het gebruiken van beide - poorten tegelijk heeft een klein probleempje, ze gaan - namelijk zo snel dat het kan gebeuren dat de counters - verspringen net nadat je de eerste hebt gelezen. Stel je - lees poort &HE6 het eerst en daar staat een 255. De kans is - dan groot dat de counter vlak daarna wordt verhoogd, en je - leest dan bijvoorbeeld de waarde 18 bij poort &HE7. Dit moet - dan echter 17 zijn! - - - T O E P A S S I N G E N - - Er zijn natuurlijk vele toepassingen, maar de belangrijkste - is wel bij samplen. De samplechip heeft trouwens z'n eigen - counter, die echter maar 2 bits is en wordt gebruikt voor de - timing bij de _PCMPLAY/_PCMREC commando's in BASIC. Deze - counter loopt op de bekende 15.75 kHz, de snelheid bij een - _PCMxxx comando met snelheidsparameter 0. - - Als we een sample play of record routine in ML willen maken, - kunnen we beter van de low byte van de 16 bits counter - gebruik maken, omdat die veel nauwkeuriger is. - - De counter wordt ook veel gebruikt bij afspeelroutines van - muziek voor MSX-MUSIC en MSX-AUDIO. Bij deze chips moet er - namelijk bij het beschrijven van de registers steeds even - gewacht worden. Routines die voor de Z80 zijn geschreven - gebruiken dan bijvoorbeeld twee keer EX SP,(HL), maar dat - duurt bij de R800 te kort waardoor het mis gaat. - - - M O O N B L A S T E R - - Als voorbeeld hier even een klein stukje van de MoonBlaster - replay. De replay kijkt zelf of hij onder R800 draait, en - indien dat het geval is zal hij aangepaste routines - gebruiken om de registers van de MSX-MUSIC en MSX-AUDIO te - beschrijven. Als voorbeeld hier MSX-MUSIC. - - PAROUT: EX AF,AF - CALL TRBWT ; wacht indien nodig - LD A,C - OUT (&H7C),A ; selecteer register - IN A,(&HE6) ; lees counter - LD (RTEL),A ; sla waarde op - EX AF,AF - OUT (&H7D),A ; schrijf waarde - RET - - TRBWT: PUSH BC - LD A,(RTEL) ; stand counter bij vorige keer - LD B,A - TRBWL: IN A,(&HE6) ; lees counter - SUB B - CP 7 ; al minimaal 7 verhoogd? - JR C,TRBWL - POP BC - RET - - Door de routine TRBWT (TuRBo WaiT) wordt er gewacht totdat - de counter sinds de vorige keer dat er een register werd - beschreven 7 maal is verhoogd. De huidige waarde van de - counter wordt in (RTEL) opgeslagen voor de volgende keer dat - deze routine wordt aangeroepen. - - - B A S I C - - In BASIC kan de counter ook worden gebruikt, er is namelijk - een speciaal BASIC commando voor. Dit is echter wel een - simpel commando, het kan alleen maar wachten! Wat een humor. - Je koopt een snelle computer en ÇÇn van de nieuwe BASIC - commando's dient om te wachten! Enfin, de syntax van het - nieuwe commando is: - - _PAUSE(x) - - waarbij voor x een getal tussen 1 en 32767 kan worden - ingevuld. De computer zal dan wachten totdat de high byte - van de counter (frequentie ca. 1 kHz) het opgegeven aantal - stapjes is verhoogd. Hiermee kunnen we de dus tot op 1/1000 - seconde nauwkeurig wachten. Bijvoorbeeld: - - _PAUSE(1000) - - wacht precies een seconde (N.B. Eigenlijk moet dit 999 zijn, - want zoals we weten loopt de high byte van de counter op 999 - Hz.) - - Meer valt er eigenlijk niet over de counter te zeggen. Voor - langere tijdmeting is hij niet geschikt, want hij doet er - maar ruim een kwart seconde over om "klokkie rond" te gaan. - - Stefan Boer - \ No newline at end of file diff --git a/Sunrise Special/3/VDP Commando Registers.md b/Sunrise Special/3/VDP Commando Registers.md deleted file mode 100644 index 64df29d..0000000 --- a/Sunrise Special/3/VDP Commando Registers.md +++ /dev/null @@ -1,326 +0,0 @@ - V D P C O M M A N D O R E G I S T E R S I N M L - - - Als extraatje bij de VDP cursus op herhaling deze keer een - tekst over het gebruik van de commando's van de VDP in ML, - met een zeer handige standaardroutine. - - De theorie die in deze tekst gebruikt wordt staat allemaal - in VDP cursus (op herhaling) deel 1 t/m 4, die resp. op - Sunrise Special #2 en deze Sunrise Special #3 zijn te - vinden. Ik zal daar hier dus weinig aandacht aan besteden. - - - I N D I R E C T - - U kunt de VDP een commando (copy, line, etc.) laten - uitvoeren door de registers R#32 t/m R#46 te beschrijven. - Zodra R#46 met de code voor het commando wordt beschreven, - zal de VDP het commando gaan uitvoeren. - - Was de VDP op dat moment echter nog met een ander commando - bezig, dan zal het in de soep lopen. Daarom moet altijd - eerst gecheckt worden of de VDP al klaar was met het vorige - commando, door bit 0 van statusregister S#2 te lezen. - - Het schrijven van 15 opeenvolgende registers gaat het - makkelijkst met de indirecte methode. Hierbij schrijven we - eerst het startregister naar R#17, en we sturen de data - daarna naar Port #3 (I/O adres &H9B). De waarde van R#17 zal - automatisch worden verhoogd. - - Het Z80 commando OTIR is hiervoor uitermate geschikt. Dit - commando stuurt B bytes uit het geheugen vanaf adres (HL) - naar poort (C). Hiervan zullen we in de routine dan ook - gebruik maken. - - Meer dan genoeg theorie, het is nu hoog tijd voor de - universele VDP commando routine. Ik heb hem vroeger DOCOPY - gedoopt, omdat hij het meest voor copy's wordt gebruikt, - maar dat is dus wel een beetje misleidende naam want hij kan - voor alle commando's worden gebruikt. Ik ben zo gewend - geraakt aan die naam dat ik hem ben blijven gebruiken. - - - D O C O P Y - - Hier komt de source, zoals gewoonlijk in mijn favoriete - assembler (WB-ASS2). - - ; DOCOPY - ; Voer VDP commando uit - ; In: HL=start data - ; Gebruikt: AF, AF', HL, BC - - DOCOPY: LD BC,&H0F9B - CALL VDPRDY - DI - LD A,32 - OUT (&H99),A - LD A,17+128 - OUT (&H99),A - EI - OTIR - RET - - Eerst wordt B geladen met de waarde 15 (we willen 15 - registers beschrijven) en C met &H9B (we willen naar poort - &H9B schrijven). Een LD BC,.. commando is korter en sneller - dan een LD B,.. en een LD C,.. commando. De routine VDPRDY - (VDP ReaDY) wacht tot de VDP klaar is met het uitvoeren van - een eventueel vorig commando dat nog bezig is. - - Vervolgens wordt het startregister naar R#17 geschreven. - Zoals gewoonlijk moeten de interrupts hierbij uit staan. De - interrupts staan ook bij de OTIR nog uit, want na een EI - duurt het nog een instructie voordat de interrupts weer aan - gaan! Dit is overigens niet strikt noodzakelijk, alleen als - er in de interrupt routine iets met de VDP gebeurt moeten - de interrupts bij de OTIR ook per se uit staan. Simpel hä? - Nu de routines VDPRDY en RDSTAT (die weer door VDPRDY wordt - aangeroepen) nog: - - - ; VDPRDY - ; Wacht tot VDP klaar is met command execute - ; Gebruikt: AF, AF' - - VDPRDY: LD A,2 - CALL RDSTAT - BIT 0,A - JP NZ,VDPRDY - - ; RDSTAT - ; Lees VDP statusregister - ; In: A=S# - ; Uit: A=data - ; Gebruikt: AF' - - RDSTAT: DI - OUT (&H99),A - LD A,15+128 - OUT (&H99),A - NOP - NOP - IN A,(&H99) - EX AF,AF - XOR A - OUT (&H99),A - LD A,128+15 - OUT (&H99),A - EI - EX AF,AF - RET - - - Dit is een bekende routine, dus verdere uitleg is hier - overbodig. De interrupts worden steeds even weer aangezet - tijdens het uitvoeren van VDPRDY, omdat anders bijvoorbeeld - de muziek gaat haperen. Het zou in principe ook mogelijk - zijn om S#2 constant te lezen, maar dan zouden de interrupts - uit moeten staan zolang het vorige commando nog niet - afgelopen is, en dat kan soms te lang duren. - - - P R A K T I J K - - Een praktijkvoorbeeldje maakt dit wat duidelijker. Stel we - willen het blok (0,0)-(49,99) op page 3 kopiâren naar - (20,70) op page 1 met een high speed copy (HMMM). Dit gaat - dan als volgt: - - COPY: LD HL,COPDAT - JP DOCOPY - COPDAT: DB 0,0,0,3 ; source - DB 20,0,70,1 ; destination - DB 50,0,100,0 ; grootte - DB 0,0,&HD0 ; HMMM - - Voor alle VDP commando's dus een blokje van 15 bytes maken, - het gaat het handigste als je het op bovenstaande wijze - indeelt. Je ziet dat de page nummers gewoon de high bytes - van de y coîrdinaten zijn, dus het opgeven van de page gaat - heel simpel. &HD0 is de code voor HMMM (high speed move VRAM - to VRAM). - - - H M M C - - Tot slot nog een voorbeeldje van een iets ingewikkelder - commando, namelijk HMMC. Dit is wel een zeer belangrijk - commando, omdat je hiermee een plaatje uit het RAM naar het - VRAM kunt kopiâren, waarbij dit plaatje een willekeurige - rechthoek mag zijn. Bij gewoon RAM naar VRAM kopiâren kun je - alleen een bepaald adresbereik van het VRAM vullen, nu dus - gewoon een rechthoek zoals bij een normale copy. - - De werking van HMMC wordt uitgelegd in deel 3 van de cursus. - In de voorbeeldroutine wordt er een zwart 8*8 blokje met een - witte letter A naar het scherm gekopieerd op positie - (124,102) op page 0, dit werkt zowel op SCREEN 5 als SCREEN - 7. Ik gebruik hier de procedure zoals omschreven in het VDP - Technical Databook, dezelfde procedure die ik ook bij HMMC - in VDP cursus deel 3 heb gezet. - - - LD A,(GRPDAT) - LD (COPDAT+12),A ; vul eerste byte alvast in - LD HL,COPDAT - CALL DOCOPY - - - Hier wordt het commando al naar de VDP gestuurd. De - grafische data staat van GRPDAT, je ziet dat hier de eerste - byte alvast wordt meegegeven bij het geven van het commando. - Dit is overigens verplicht. - - - DI - LD A,44+128 ; R#44, geen auto increment - OUT (&H99),A - LD A,17+128 - OUT (&H99),A - EI - - - We gebruiken nu weer indirecte adressering om de data naar - de VDP te sturen. De data moet namelijk steeds naar R#44 - worden geschreven. We kunnen de indirecte methode ook - gebruiken om steeds naar ÇÇn register te schrijven, waarbij - de auto increment van R#17 dus uit staat. Dit kan door bit 7 - van R#17 te zetten (in de routine ziet u dus 44+128 staan). - - - LD HL,GRPDAT+1 - COPY: LD A,2 - CALL RDSTAT - BIT 0,A - RET Z - BIT 7,A - JP Z,COPY - LD A,(HL) - OUT (&H9B),A - INC HL - JP COPY - - - Hier wordt volgens de gegeven procedure de data naar R#44 - geschreven. Steeds wordt S#2 gelezen. Bit 0 is CE (Command - Execute), als dat bit 0 is, is het commando klaar. Bit 7 is - TR, dat aangeeft of de VDP klaar is voor de volgende byte. - Zo nee, dan lezen we S#2 opnieuw, zo ja, dan sturen we de - volgende byte naar Port #3, en dus naar R#44. Dit wordt - steeds herhaald totdat het klaar is. - - - COPDAT: DB 0,0,0,0 ; source (hier niet gebruikt) - DB 124,0,102,0 ; destination - DB 8,0,8,0 ; grootte - DB 0,0,&HF0 ; HMMC - - - Het blokje met de 15 bytes. De eerste bytes worden hier niet - gebruikt, dus daar heb ik gewoon 0 voor ingevuld. Je zou - eventueel ook een aangepaste DOCOPY kunnen maken die 11 - bytes stuurt naar R#36-R#45, maar de tijdwinst die daarmee - behaald wordt is zo minimaal dat dat weinig nut heeft. - - Let op: de grootte wordt altijd in pixels aangegeven, dus - niet in bytes! Ons blokje van 8*8 is maar 4*8 bytes. Die - bytes volgen nu. Een 1 staat voor zwart, een F voor wit. Als - je goed kijkt kun je de hoofdletter A erin zien. Uiteraard - kan hier elke willekeurige data worden ingevuld, het gaat - hier alleen om het voorbeeld. - - - GRPDAT: DB &H11,&H1F,&H11,&H11 - DB &H11,&HF1,&HF1,&H11 - DB &H1F,&H11,&H1F,&H11 - DB &HF1,&H11,&H11,&HF1 - DB &HF1,&H11,&H11,&HF1 - DB &HFF,&HFF,&HFF,&HF1 - DB &HF1,&H11,&H11,&HF1 - DB &HF1,&H11,&H11,&HF1 - - - K A N H E T N I E T S N E L L E R ? - - Dit werkt uitstekend, maar je vraagt je toch af: kan het - niet sneller? Dit was de procedure zoals die wordt - voorgeschreven door het Technical Databook, maar volgens mij - mag het ook op onderstaande manier. Het werkt in ieder geval - prima. - - Het blijkt namelijk dat de VDP de data die naar R#44 wordt - geschreven behoorlijk snel kan verwerken (Nvdr: misschien is - de R800 of de Z80 wel te langzaam), waardoor het helemaal - niet nodig is om TR steeds te checken. En CE checken is al - helemaal onzin, we weten immers wel hoeveel bytes we moeten - sturen. Dan kun je het ook als volgt programmeren: - - LD A,(GRPDAT) - LD (COPDAT+12),A ; vul eerste byte alvast in - LD HL,COPDAT - CALL DOCOPY - DI - LD A,44+128 ; R#44, geen auto increment - OUT (&H99),A - LD A,17+128 - OUT (&H99),A - EI - - - Tot hier is het exact hetzelfde. Nu komt het gedeelte dat is - veranderd: - - - LD HL,GRPDAT+1 - LD BC,&H1F9B ; 31 bytes naar port #3 - OTIR - RET - - - Dat is alles! (Ik laat COPDAT en GRPDAT nu achterwege, zijn - toch hetzelfde.) We moesten in totaal 4*8=32 bytes sturen, - waarvan er ÇÇn al is verstuurd bij het geven van het - commando. Die bytes moeten naar Port #3 worden gestuurd, - ofwel I/O poort &H9B. De data staat vanaf GRPDAT+1 (we - hadden de eerste byte immers al verstuurd), dus is een OTIR - voldoende! Bij copy's groter dan 256 bytes kun je OTIR - natuurlijk niet gebruiken, maar dat kan als volgt worden - opgelost: - - LD HL,GRPDAT+1 - LD BC,aantal bytes - COPY: LD A,(HL) - OUT (&H9B),A - INC HL - DEC BC - LD A,B - OR C - JP NZ,COPY - - - Als je 'normaal' RAM naar VRAM wilt verplaatsen, zet je - eerst de VDP klaar om VRAM te schrijven vanaf het gewenste - adres, en daarna stuur je de data naar Port #0 (&H98). - - Op de 'copy manier' (met HMMC dus) gaat het dus net zo snel, - en het werkt analoog. Eerst de VDP een HMMC klaar zetten om - de data te ontvangen (het HMMC commando geven met DOCOPY) en - daarna de data naar Port #3 schrijven (&H9B). Het voordeel - hiervan is dat je nu niet tot een bepaald adresgebied - beperkt bent. Als je bijvoorbeeld het gebied (100,100)- - (199,199) met data uit het RAM zou willen vullen, zou je bij - de 'normale' manier voor elke lijn opnieuw de VDP in moeten - stellen, terwijl dat met HMMC niet nodig is. - - HMMC is dus een zeer handig commando, vooral als je in een - programma een keer VRAM te kort komt. Je kunt de gewenste - graphics dan steeds razendsnel met HMMC uit het RAM halen. - - Veel succes met je eigen VDP routines en tot de volgende - keer! - - Stefan Boer - \ No newline at end of file diff --git a/Sunrise Special/3/VDP Cursus 3.md b/Sunrise Special/3/VDP Cursus 3.md deleted file mode 100644 index 3e810ce..0000000 --- a/Sunrise Special/3/VDP Cursus 3.md +++ /dev/null @@ -1,274 +0,0 @@ - M S X 2 / 2 + V D P C U R S U S ( 3 ) - - - - D E C O M M A N D O R E G I S T E R S - - Zoals beloofd behandelen we deze keer de commando registers. - Hiermee kunt u de VDP laten kopiâren, lijnen trekken, etc. - Nu volgt eerst een overzicht van de commando's, logische be- - werkingen en commando registers. - - - O V E R Z I C H T - - Naam: Doel: Bron: Eenh: Mnemonic: CM3 CM2 CM1 CM0 - ----------------------------------------------------------- - High- VRAM CPU Byte HMMC 1 1 1 1 - Speed VRAM VRAM Byte YMMM 1 1 1 0 - Move VRAM VRAM Byte HMMM 1 1 0 1 - VRAM VDP Byte HMMV 1 1 0 0 - Logical VRAM CPU Dot LMMC 1 0 1 1 - Move CPU VRAM Dot LMCM 1 0 1 0 - VRAM VRAM Dot LMMM 1 0 0 1 - VRAM VDP Dot LMMV 1 0 0 0 - Line VRAM VDP Dot LINE 0 1 1 1 - Search VRAM VDP Dot SRCH 0 1 1 0 - Pset VRAM VDP Dot PSET 0 1 0 1 - Point VDP VRAM Dot POINT 0 1 0 0 - Invalid 0 0 1 1 - Invalid 0 0 1 0 - Invalid 0 0 0 1 - Stop STOP 0 0 0 0 - ------------------------------------------------------------ - - Het commando wordt uitgevoerd door de VDP door de juiste - waarde van CM3-CM0 naar R#46 te schrijven. De juiste data - moet echter eerst naar R#32-R#45 worden geschreven (zie - verderop). Bit 0 van S#2 (CE = Command Execute), heeft de - waarde 1 als het commando wordt uitgevoerd, en de waarde 0 - als het klaar is. De werking van deze commando's is alleen - gegarandeerd in de modes G4-G7 (SCREEN 5 t/m 8, op MSX2+ - natuurlijk ook in SCREEN 10 t/m 12). Gebruik STOP om een - commando af te breken dat wordt uitgevoerd. - - - L O G I S C H E O P E R A T I E S - - Naam: Werking: LO3 LO2 LO1 LO0 - ----------------------------------------------------------- - IMP DC=SC 0 0 0 0 - AND DC=SC*DC 0 0 0 1 - OR DC=SC+DC 0 0 1 0 - EOR DC=NOT(SC)*DC+SC*NOT(DC) 0 0 1 1 - NOT DC=NOT(SC) 0 1 0 0 - TIMP if SC=0 then DC=DC else IMP 1 0 0 0 - TAND if SC=0 then DC=DC else AND 1 0 0 1 - TOR if SC=0 then DC=DC else OR 1 0 1 0 - TEOR if SC=0 then DC=DC else EOR 1 0 1 1 - TNOT if SC=0 then DC=DC else NOT 1 1 0 0 - ----------------------------------------------------------- - - SC = Source Color (bron), DC = Destination Color (doel). EOR - is hetzelfde als XOR in BASIC. De logische operaties mogen - worden toegepast bij LINE, PSET en LOGICAL MOVE commando's. - De juiste waarde van LO3-LO0 moet gelijktijdig met het - commando naar R#46 worden geschreven. - - - H E T C O O R D I N A T E N S Y S T E E M - - De VDP werkt met een ander coîrdinatensysteem dan MSX-BASIC. - Alle pages worden als het ware aan elkaar geplakt tot ÇÇn - groot scherm, waarbij de Y-coîrdinaten gewoon doorlopen. In - onderstaand overzicht is te zien hoe dat werkt. In het - midden staan de corresponderende adressen in het VRAM. - - G4 (SCREEN 5) Adres: G5 (SCREEN 6) - - -------------------------- 00000H -------------------------- - (000,000) (255,000) (000,000) (511,000) - Page 0 Page 0 - (000,255) (255,255) (000,255) (511,255) - -------------------------- 08000H -------------------------- - (000,256) (255,256) (000,256) (511,256) - Page 1 Page 1 - (000,511) (255,511) (000,511) (511,511) - -------------------------- 10000H -------------------------- - (000,512) (255,512) (000,512) (511,512) - Page 2 Page 2 - (000,767) (255,767) (000,767) (511,767) - -------------------------- 18000H -------------------------- - (000,768) (255,768) (000,768) (511,768) - Page 3 Page 3 - (000,1023) (255,1023) (000,1023) (511,1023) - -------------------------- 1FFFFH -------------------------- - - G7 (SCREEN 8) G6 (SCREEN 7) - - -------------------------- 00000H -------------------------- - (000,000) (255,000) (000,000) (511,000) - Page 0 Page 0 - (000,255) (255,255) (000,255) (511,255) - -------------------------- 10000H -------------------------- - (000,256) (256,256) (000,256) (511,256) - Page 1 Page 1 - (000,511) (255,511) (000,511) (511,511) - -------------------------- 1FFFFH -------------------------- - - Op het scherm zijn 212 (of 192) lijnen van dezelfde PAGE te - zien. Welke dat zijn kunt u instellen met R#23. - - - P A G E S - - PAGEs werken ook anders in ML, er is geen SET PAGE commando - of iets dergelijks. De PAGE die wordt getoond kan worden - ingesteld met R#2. U kunt daarbij het volgende tabelletje - gebruiken: - - Page: 0 1 2 3 - R#2: &H1F &H3F &H5F &H7F - - Bij het schrijven van VRAM in ÇÇn van de pages moet u gewoon - het juiste adres instellen, zie hiervoor deel 2 van de - cursus (de bits in R#14 bepalen daarbij de page). - - Bij kopiâren, lijnen trekken, etc. is er voor de VDP - helemaal geen sprake van PAGEs. De coîrdinaten lopen zoals - in bovenstaand overzicht te zien is gewoon door. Om de VDP - iets in een bepaalde pagina te laten doen, moet gewoon de - juiste waarde bij de y coîrdinaat worden opgeteld. - - Voorbeeld: stel u wilt een lijn trekken op page 3, van (23, - 68) naar (203,176). Dat wordt dan (23,68+768) en (203,176+ - 768). Het is dus niet nodig R#2 hiervoor te veranderen. - - In de praktijk gaat het werken met pages heel gemakkelijk, - omdat het gewoon de high byte van de y coîrdinaat is. Bij de - standaardmethode om een commando naar de VDP te sturen die - we nog zullen behandelen wijst zich dat vanzelf. - - - C O M M A N D O R E G I S T E R S - - Hieronder volgt een schematisch overzicht van de registers, - zoals we gewend zijn op binair niveau. - - MSB 7 6 5 4 3 2 1 0 LSB - ------------------------------------------------------------ - R#32 SX7 SX6 SX5 SX4 SX3 SX2 SX1 SX0 Source X Low - R#33 0 0 0 0 0 0 0 SX8 Source X High - R#34 SY7 SY6 SY5 SY4 SY3 SY2 SY1 SY0 Source Y Low - R#35 0 0 0 0 0 0 SY9 SY8 Source Y High - - R#36 DX7 DX6 DX5 DX4 DX3 DX2 DX1 DX0 Dest. X Low - R#37 0 0 0 0 0 0 0 DX8 Dest. X High - R#38 DY7 DY6 DY5 DY4 DY3 DY2 DY1 DY0 Dest. Y Low - R#39 0 0 0 0 0 0 DY9 DY8 Dest. Y High - - R#40 NX7 NX6 NX5 NX4 NX3 NX2 NX1 NX0 Nr of dots X Low - R#41 0 0 0 0 0 0 0 NX8 Nr of dots X Hgh - R#42 NY7 NY6 NY5 NY4 NY3 NY2 NY1 NY0 Nr of dots Y Low - R#43 0 0 0 0 0 0 NY9 NY8 Nr of dots Y Hgh - - R#44 CH3 CH2 CH1 CH0 CL3 CL2 CL1 CL0 Color register - R#45 0 MXC MXD MXS DIY DIX EQ MAJ Argument reg. - R#46 CM3 CM2 CM1 CM0 LO3 LO2 LO1 LO0 Command register - ------------------------------------------------------------ - - - Ik zal nu alle commando's ÇÇn voor ÇÇn gaan bespreken. Omdat - dat veel ruimte in beslag neemt, zal het over twee delen - worden verdeeld. Opmerking vooraf: bit 5 van R#45 bepaalt of - het VRAM (0) of Expansion RAM (1) wordt gebruikt. - - - H M M C - - High Speed Move CPU to VRAM - - Dit commando doet ongeveer hetzelfde als COPY TO - (X,Y) in Basic. Het schrijft data van de CPU naar een - rechthoek. Geef met DX, DY, NX, NY, DIX en DIY de gewenste - rechthoek aan. DIX en DIY werken als volgt: - - DIX: 0 = naar rechts vanaf DX, 1 = naar links vanaf DX - DIY: 0 = naar onder vanaf DY, 1 = naar boven vanaf DY - - De data moet steeds naar R#44 worden geschreven. Schrijf bij - het geven van het commando alvast de eerste byte naar R#44. - De opbouw van R#44 verschilt per schermmode: - - G4, G6 (SC5,7): CR7 CR6 CR5 CR4 CR3 CR2 CR1 CR0 - linker pixel rechter pixel - - G5 (SC6) : CR7 CR6 CR5 CR4 CR3 CR2 CR1 CR0 - links midlinks midrechts rechts - - G7 (SC8) : CR7 CR6 CR5 CR4 CR3 CR2 CR1 CR0 - ÇÇn pixel - - Dit omdat de data per byte moet worden verzonden, en in G4- - G6 meer dan ÇÇn pixel in een byte wordt opgeslagen. Hierdoor - worden er ook bits van NX en DX verwaarloosd. In G5 bit 0 en - 1, in G4 en G6 alleen bit 0. - - Als alles goed is ingevuld, schrijf je de waarde 11110000B - naar R#46. Vervolgens moet steeds S#2 worden uitgelezen, en - gekeken worden of TR of CE gelijk zijn aan 0. - - MSB 7 6 5 4 3 2 1 0 - S#2 TR VR HR BD 1 1 EO CE Status reg. 2 - - De volgende byte mag naar R#44 worden geschreven als TR - gelijk is aan 1. Het commando is klaar als CE gelijk is aan - 0. - - In schema: - 1) Schrijf de juiste waardes naar R#36-R#45 - 2) Schrijf 11110000B naar R#46 - 3) Lees S#2 - 4) Als CE=0 dan is het klaar - 5) Als TR=0 dan 3 - 6) Schrijf volgende byte naar R#44 - 7) Ga naar 3 - - - Y M M M - - High Speed Move VRAM to VRAM, y only - - Dit commando verplaatst de rechthoek die wordt aangegeven - door DX, SY, NY, DIX en DIY en de rand van het scherm aan de - rechterkant (of linkerkant, als DIX=1) naar eenzelfde blok, - echter met Y-coîrdinaat DY. Omdat het met bytes gaat, worden - in G4-G6 weer dezelfde bits van de X-coîrdinaten verwaar- - loosd als bij HMMC. - - Instellen van het YMMM commando: - R#34 en R#35: y-coîrdinaat van bron - R#36 en R#37: x-coîrdinaat van bron än doel - R#38 en R#39: y-coîrdinaat van doel - R#42 en R#43: lengte van rechthoek in Y-richting - R#45 : bepaal richting en soort VRAM - - Schrijf 11100000B naar R#46 om het commando uit te voeren, - het is klaar als CE gelijk is aan 0. - - - H M M M - - High Speed Move VRAM to VRAM - - Dit is een van de meest gebruikte commando's. Het verplaatst - de rechthoek die wordt aangegeven door SX, SY, NX, NY, DIX - en DIY naar het punt DX,DY. Weer worden de laagste bits van - de X-coîrdinaten verwaarloosd in G4-G6. - - Het commando is te vergelijken met COPY (SX,SY)- STEP(NX,NY) - TO (DX,DY) in Basic, met het verschil dat hierbij de x- - coîrdinaat een veelvoud van 2 (G4, G6) of 4 (G5) moet zijn. - Het is daarom ook sneller. - - Instellen van het HMMM commando: - Schrijf de juiste waardes naar R#32-R#43 en R#45. - - Schrijf 11010000B naar R#46 om het commando uit te voeren, - het is klaar als CE gelijk is aan 0. - - In het volgende deel volgt de rest van de commando's. Tot - dan! - - Stefan Boer - \ No newline at end of file diff --git a/Sunrise Special/3/VDP Cursus 4.md b/Sunrise Special/3/VDP Cursus 4.md deleted file mode 100644 index 674ef1f..0000000 --- a/Sunrise Special/3/VDP Cursus 4.md +++ /dev/null @@ -1,384 +0,0 @@ - M S X 2 / 2 + V D P C U R S U S ( 4 ) - - - Het laatste commado dat ik de vorige keer heb behandeld was - HMMM. Voordat we verdergaan, eerst nog even iets anders. - - - V E R S N E L L E N - - Er zijn twee methodes om het uitvoeren van de commando's - door de VDP te versnellen. - - 1) Zet de sprites uit - Als bit 1 van R#8 gelijk wordt gemaakt aan 1, kan de tijd - die normaal voor het weergeven van sprites wordt gebruikt - nu gebruikt worden voor het uitvoeren van commando's. Dat - gaat daardoor nu sneller. - - 2) Zet het scherm uit - Als bit 6 van R#1 gelijk wordt gemaakt aan 0, kan de tijd - die normaal voor het weergeven van het scherm wordt - gebruikt nu gebruikt worden voor het uitvoeren van - commando's. Dat gaat daardoor nu sneller. - - U kunt dit bijvoorbeeld gebruiken bij flip-screens (wordt - veel bij MSX2 spellen gebruikt, er is geen scrolling maar - als je het scherm uitloopt wordt het even zwart, waarna - het volgende scherm wordt getoond). Je kunt het scherm - namelijk ook zwart maken door PAGE 1 zwart te maken en - die te tonen. De schermopbouw gaat echter sneller als u - bit 6 van R#1 gebruikt. - - Ik ga nu verder met het overzicht van alle commando's. - - - H M M V - - High-speed move VDP to VRAM - - Dit commando vult een bepaalde rechthoek met een bepaalde - kleur. Het doet dus hetzelfde als LINE,BF in BASIC. - - High speed betekent geen logische bewerking en transport per - byte. De uitvoering is daarom veel sneller. Het nadeel van - transport per byte is dat in SCREEN 5 en 7 (G4 en G6) de X - coîrdinaat een veelvoud moet zijn van 2, en in SCREEN 6 - (G5), de X coîrdinaat een veelvoud moet zijn van 4. - - De volgende registers hebben betekenis bij HMMV: - - NX: grootte van rechthoek in X richting R#40, R#41 - NY: grootte van rechthoek in Y richting R#42, R#43 - DX: X coîrdinaat R#36, R#37 - DY: Y coîrdinaat R#38, R#39 - DIX, DIY: richting R#45 - CLR: kleur R#44 - - Nadat bovenstaande data naar de juiste registers is - geschreven kan het commando worden uitgevoerd door de waarde - &B11000000 naar R#46 te schrijven. CE geeft aan of de VDP al - klaar is (=0) of niet (=1). - - Let op: R#44 bevat niet het kleurnummer, maar de byte die - geschreven moet worden. Bij SCREEN 5, 6 en 7 kun je dus - verticale strepen maken. Zie voor de opbouw van de byte het - commando HMMC in het vorige deel. - - - L M M C - - Logical move CPU to VRAM - - Dit commando verplaatst data van de microprocessor naar het - VRAM naar een bepaalde rechthoek. De data wordt per pixel - verstuurd, er kunnen dus logische bewerkingen worden - toegepast. Er zijn ook geen beperkingen op de x coîrdinaten. - - De volgende registers moeten eerst met de juiste waarden - worden gevuld: - - R#36, R#37: DX X coîrdinaat bestemming - R#38, R#39: DY Y coîrdinaat bestemming - R#40, R#41: NX grootte in X-richting - R#42, R#43: NY grootte in Y-richting - R#44 : data de juiste data - R#45 : DIX, DIY de juiste richting - - Daarna kunt u het commando laten uitvoeren door &B1011---- - naar R#46 te schrijven. Op de plaats van ---- kunt u de code - van de gewenste logische operatie schrijven (0000 is geen - logische operatie). - - De data wordt nu per pixel verzonden. Dat gaat als volgt: - - MSB 7 6 5 4 3 2 1 0 LSB - R#44 - - - - C3 C2 C1 C0 G4 en G6 - R#44 - - - - - - C1 C0 G5 - R#44 C7 C6 C5 C4 C3 C2 C1 C0 G7 en hoger - - Dit commando is de langzamere versie van HMMC. Er kunnen nu - echter wel logische bewerkingen worden gebruikt. Ook is elke - X coîrdinaat mogelijk. Ik geef ook weer het werkschema: - - 1 Stel de commando registers in - 2 Schrijf &B1011---- naar R#46 (logische bewerking op ----) - 3 Lees S#2 - 4 Als CE gelijk is aan 0, dan is het klaar - 5 Als TR gelijk is aan 0, dan is het verzenden nog niet - klaar, ga terug naar 3 - 6 Anders kan nu de data naar R#44 worden geschreven - 7 Ga verder bij 3 - - - L M C M - - Logical move VRAM to CPU - - Dit commando verplaatst data van een bepaalde rechthoek per - pixel naar de CPU. Het is onzin hierbij een logische - bewerking te gebruiken. - - De volgende registers moeten worden ingevuld: - - R#32, R#33: SX Bron X coîrdinaat - R#34, R#35: SY Bron Y coîrdinaat - R#40, R#41: NX Grootte van rechthoek in X richting - R#42, R#43: NY Grootte van rechthoek in Y richting - R#45 : DIY, DIX Richting - - Het commando wordt uitgevoerd door de waarde &B10100000 naar - R#46 te schrijven. De data kan dan uit S#7 worden gelezen. - Denk er daarbij om dat de data verschilt per screenmode. Het - overzicht is hetzelfde als de data die bij het vorige - commando naar CLR moest worden geschreven. Ik geef u voor de - duidelijkheid wederom een werkschema: - - 1 Lees S#7 - 2 Schrijf de juiste waardes naar de commando registers - 3 Schrijf &B10100000 naar R#46 - 4 Lees S#2 - 5 Als TR=0 dan transport nog niet klaar, ga naar 4 - 6 Lees S#7 en doe met de waarde wat u wilt - 7 Als CE gelijk is aan 0 is het commando klaar - 8 Ga anders naar 4 - - Let op: - TR moet op 0 worden gezet voordat het commando wordt - uitgevoerd. Daarom moeten eerst S#7 worden gelezen. Ook al - is de data naar S#7 geschreven en TR=1, zal daarna toch het - commando worden afgemaakt en zal CE gelijk worden gemaakt - aan 0. - - - L M M M - - Logical move VRAM to VRAM - - Het LMMM commando verplaatst de data van het aangegeven - rechthoekige stuk naar een ander rechthoekig stuk. Omdat dit - gaat in eenheden van pixels, kunt u logische operaties - gebruiken. Ook dit is een zeer veel gebruikt commando. - - De volgende registers moeten eerst van de juiste waarde - worden voorzien: - - R#32, R#33: SX Bron X coîrdinaat - R#34, R#35: SY Bron Y coîrdinaat - R#36, R#37: DX Doel X coîrdinaat - R#38, R#39: DY Doel Y coîrdinaat - R#40, R#41: NX Grootte X richting - R#42, R#43: NY Grootte Y richting - R#45 : DIX, DIY Richting - - Schrijf &B1001---- naar R#46 om het commando uit te voeren. - U kunt op de streepjes de gewenste logische bewerking - invullen. - - Dit commando wordt door MSX BASIC 2.0 en hoger gebruikt voor - COPY (SX,SY)-STEP(NX,NY) TO (DX,DY),,. - - - L M M V - - Logical move VDP to VRAM - - Dit commando doet hetzelfde als HMMV, met het verschil dat - er nu wel logische bewerkingen kunnen worden toegepast en - dat het transport nu met pixels in plaats van bytes gebeurt. - De X coîrdinaat kan dus elke waarde hebben. Het gaat daarom - ook langzamer. - - Dit commando wordt in MSX BASIC 2.0 en hoger gebruikt voor - LINE(DX,DY)-STEP(NX,NY),CLR,BF,. - - Voor de werking verwijs ik dus naar HMMV, er moet nu echter - &B1000---- naar R#46 worden geschreven, en op de laagste - vier bits de logische bewerking. Van de X coîrdinaat worden - alle bits behouden. - - - L I N E - - De naam zegt het al, met dit commando kunt u de VDP lijnen - laten trekken. Die lijn die wordt getekend is de schuine - lijn van een rechthoekige driehoek. (Dat is een driehoek - waarvan twee zijden loodrecht op elkaar staan.) De twee - rechthoekszijden worden aangegeven als afstanden vanaf ÇÇn - punt. (Dat is het punt waar de rechte hoek zit.) - - De volgende registers moet u beschrijven met de juiste - waardes: - - R#36, R#37: DX X coîrdinaat - R#38, R#39: DY Y coîrdinaat - R#40, R#41: MJ grootte van de langste zijde (NX) - R#42, R#43: MI grootte van de kortste zijde (NY) - R#45 : DIX richting van de rechthoekszijden - vanaf het punt (DX,DY) - 0: rechts 1: links - : DIY 0: omlaag 1: omhoog - : MAJ 0: lange zijde is X - 1: lange zijde is Y - R#44 : C Kleur (G4,G6 0-15; G5 0-3; G7 0-255) - - Schrijf &B0111---- naar R#46 om de lijn te trekken. Op de - streepjes kunt u een eventuele logische bewerking invullen. - - Dit is erg ingewikkeld. Zoals al eerder aangekondigd zullen - in latere delen van de VDP cursus vele toepassingen van het - geleerde behandeld worden, voorzien van zeer uitgebreide - uitleg. Daar zal ook zeker een routine voor lijnen bij - zitten. Voor de duidelijkheid geef ik u nu nog hoe het er in - BASIC uit zou zien: - - LINE (DX+MAJ,DY)-(DX,DY-MIN),C,,. - Hierbij zijn DIX, DIY en MAJ gelijk aan 0. - - Zoals gewoonlijk is CE van S#2 gelijk aan 1 als het commando - wordt uitgevoerd. - - - S R C H - - Het SRCH commando zoekt (search = zoeken) naar een pixel met - een bepaalde kleur naar de linker- of rechterkant van een - bepaald startpunt. Dit commando wordt bijvoorbeeld gebruikt - bij het PAINT commando van BASIC. - - De volgende registers worden door SRCH gebruikt: - - R#32, R#33: SX X coîrdinaat startpunt - R#34, R#35: SY Y coîrdinaat startpunt - R#44 C te zoeken kleur - R#45 : DIX Geeft zoekrichting aan (0 = rechts) - : EQ Geeft aan wanneer de VDP moet stoppen - met zoeken. 1 = stop als een pixel met - de juiste kleur is gevonden, 0 = stop - als een pixel met een andere kleur is - gevonden. - - Schrijf de waarde &B01100000 naar R#46 om het commando te - starten. De statusregisters worden als volgt beãnvloed: - - S#2 : BD Bit 4 wordt 1 als kleur gevonden - : CE Bit 0 wordt 0 als commando klaar - S#8 : BX X coîrdinaat van plaats waar gevonden - S#9 : BX Bit 0 bevat bit 8 van X coîrdinaat - Overige bits bevatten de waarde 1 - (bit 8 wordt alleen gebruikt bij G5 - en G6) - - Werkschema: - - 1) Schrijf de juiste waardes naar de commandoregisters - 2) Schrijf &B01100000 naar R#46 - 3) Lees S#2 - 4) Als CE=1 dan 3, commando nog niet klaar - 5) Als BD=0 dan klaar, kleur niet gevonden - 6) Lees S#8 en S#9 - 7) Klaar - - - P S E T - - Het PSET commando doet hetzelfde als PSET(X,Y),C, in Basic. Het zet een pixel in de kleur C op - positie (X,Y), daarbij wordt eventueel de logische bewerking - uitgevoerd met de pixel die er al stond. - - De coîrdinaten moeten in DX en DY staan, R#36-R#39. De kleur - kunt u in R#44 zetten. De volgende kleurnummers zijn - mogelijk: - - Mode: Kleurbereik: - ------------------------------- - SCREEN 5, G4 0-15 - SCREEN 6, G5 0-3 - SCREEN 7, G6 0-15 - SCREEN 8, G7 0-255 - - Schrijf de waarde &B0101---- naar R#46 om het PSET commando - uit te voeren. Op ---- kunt u eventueel een logische - operatie invullen. - - - P O I N T - - Dit commando doet het tegenovergestelde van PSET. Het leest - namelijk de kleur van een bepaald pixel. In BASIC hebben we - daarvoor het commando POINT(X,Y). - - De coîrdinaten moeten nu in SX en SY staan, R#32-R#35. De - kleur komt in S#7 te staan. Daarbij zijn dezelfde kleur- - nummers mogelijk als bij PSET. - - Schrijf de waarde &B01000000 naar R#46 om het POINT commando - uit te voeren. Het CE bit van S#2 zal tijdens het uitvoeren - van het commando de waarde 1 krijgen. Als het klaar is wordt - CE weer op 0 gezet. Dan kan S#7 worden uitgelezen. - - - N A E E N C O M M A N D O - - Dit was het einde van het overzicht van alle commando's. Tot - slot nog een overzicht van de beãnvloeding van de commando - registers door de verschillende commando's. Ofwel: hoe zien - de commandoregisters eruit als een commando is uitgevoerd. - - Het is namelijk niet nodig om alle registers steeds opnieuw - in te vullen. Sommigen behouden hun waarde. U kunt in de - tabel zien welke dat zijn. In de praktijk zullen meestal - toch alle commandoregisters worden beschreven. - - Uitleg bij de tabel: - - - Onveranderd - * Coîrdinaat aan het einde van commando (of kleurcode) - # De waarde die het register had toen het einde van het - scherm werd bereikt - - SX DY DX DY NX NY CLR CMRH CMRL ARG - ------------------------------------------------------------ - HMMC - - - * - # - 0 - - - YMMM - * - * - # - 0 - - - HMMM - * - * - # - 0 - - - HMMV - - - * - # - 0 - - - LMMC - - - * - # - 0 - - - LMCM - * - - - # * 0 - - - LMMM - * - * - # - 0 - - - LMMV - - - * - # - 0 - - - LINE - - - * - - - 0 - - - SRCH - - - - - - - 0 - - - PSET - - - - - - - 0 - - - POINT - - - - - - * 0 - - - ------------------------------------------------------------ - - N.B. De eindwaardes van SY, DY en NY (SY*, DY* en NYB) - moeten als volgt worden omgerekend: - - (DIY = 0) SY* = SY + N DY* = DY + N - (DIY = 1) SY* = SY - N DY* = DY - N - - NYB = NY - N - - Bij het LINE commando moet u nog 1 van N aftrekken als MAJ - gelijk is aan 0. - - - T O T S L O T - - Met deze theorie kunt u nu alle VDP commando's zelf - toepassen. Ik heb bij deze herhaling van de VDP cursus - echter nog een extra tekst geschreven, waarin wordt - uitgelegd hoe je de commando's het beste naar de VDP kunt - sturen, met een aantal voorbeelden. Dit staat in het submenu - onder de naam VDP CURSUS ML. - - De volgende keer zijn de statusregisters aan de beurt. Nadat - ook de sprites en de opslag van de scherminhoud behandeld - zijn zullen we een aantal zeer leuke toepassingen doornemen. - Veel succes en tot de volgende keer! - - Stefan Boer - \ No newline at end of file diff --git a/Sunrise Special/3/Werken met ASCII C.md b/Sunrise Special/3/Werken met ASCII C.md deleted file mode 100644 index 1e093ce..0000000 --- a/Sunrise Special/3/Werken met ASCII C.md +++ /dev/null @@ -1,167 +0,0 @@ - H E T W E R K E N M E T A S C I I C - - - D E E L 1 - - DE VERSCHILLEN TUSSEN ASCII C 1.1 en ASCII C 1.2 - - - Zoals wellicht bekend, zijn er diverse C compilers voor de - MSX beschikbaar, waarbij Hisoft C en ASCII C de - uitgebreidste zijn. Mijn favoriete C compiler is die van - ASCII corporation, waarvan ik mijn gebruikerservaringen zal - bespreken. In dit eerste deel zal ik vooral proberen om de - verschillen tussen versie 1.1 en 1.2 aan te geven (het - belangrijkste verschil is dat versie 1.1 voor MSX-DOS 1 is, - terwijl versie 1.2 voor MSX-DOS 2 is). Hierbij ga ik er - vanuit dat de lezer de beschikking heeft over de handleiding - van versie 1.1. - - De C compiler van ASCII corporation bestaat uit een aantal - verschillende bestanden voor de verschillende delen van het - compilatie proces. Dit maakt het gebruik van deze compiler - relatief ingewikkeld, maar daar staat wel een zeer grote - flexibiliteit tegenover. - - De compiler bestaat ten eerste uit 2 hoofdprogramma's, - namelijk: CF.COM en CG.COM, dit zijn respectievelijk de code - parser en de code generator. - - - - C F . C O M , D E P A R S E R - - De parser leest de source file in, voert hier een - syntactische analyse op uit en genereert een tijdelijke file - waar de zogenaamde parse boom in wordt opgeslagen. Deze - parser is afgeleid van de Microsoft C compiler voor CP/M. - Bij het inlezen van de source file verwerkt de parser tevens - alle include commando's. Bij include zijn er 2 syntaxen, - hierbij komen de verschillen tussen C 1.1 en C 1.2 voor het - eerst duidelijk om de hoek: - - 'syntax' C 1.1 C 1.2 - include Haal de include file van Haal de include file - "filename" dezelfde drive als de van dezelfde drive - hoofd source file. als de hoofd source - file. - include Haal de include file van Haal de include file - de default drive. uit de directory die - in het environment - item INCLUDE staat. - - Bij C 1.2 kun je dus de standaard headerfiles in een aparte - directory zetten, wat je vervolgens onder DOS doorgeeft aan - de compiler met SET INCLUDE = include directory - - - C G . C O M , D E C O D E G E N E R A T O R - - De code generator leest de tijdelijke file in en zet de - parse informatie hieruit om in machinecode. Hierbij wordt - een assembler source file gemaakt in een formaat dat - geschikt is voor M80, de reloceerbare macro assembler van - Microsoft. Deze code generator voert tevens een - (uitschakelbare) register-optimalisatie uit. Hierdoor is de - gegenereerde code behoorlijk snel (ik heb bijv. een eigen - paint routine geschreven, eenmaal in C en ter vergelijking - ook eenmaal in assembler, de handgeschreven assembler versie - was maar 10% sneller dan de gecompileerde C versie), al - maakt deze optimalisatie het compilatieproces natuurlijk wel - een stuk trager. - - Ook deze code generator is afgeleid van de code generator - van de Microsoft C compiler voor CP/M. Dit laatste heeft 1 - klein nadeel: - - Aangezien de CP/M wereld veel Intel 8080 processors - (voorloper van de Z80) kende, maakt deze code generator code - aan voor deze Intel-processor. De Z80 heeft echter een - aantal uitbreidingen t.o.v. de 8080 die hierdoor niet benut - worden. Indien ASCII corporation de code generator dus echt - goed had aangepast, dan had de gecompileerde code nog iets - beter kunnen zijn. - - Ook bij het aanmaken van de code is er een klein verschil - tussen versie 1.1 en 1.2. De eerste versie maakt namelijk - Intel formaat mnemonics aan (niet te lezen voor de Z80 - programmeurs) terwijl de tweede versie Zilog formaat - mnemonics aanmaakt (let wel, de geproduceerde code is echter - nog altijd beperkt tot de 8080 subset). - - Behalve deze code omzetters (C source naar assembler - source), bestaat de compiler ook nog uit een aantal - standaard library's en een aantal header files voor deze - library's. Bij de C compiler worden de library's in 2 - formaten meegeleverd: - - 1) In het reloceerbare .REL formaat, zodat ze met L80 - meegelinkt kunnen worden. - 2) Als een aantal C en assembler source files zodat ze - eventueel aangepast kunnen worden voor speciale - toepassingen. - - Er zijn 4 reloceerbare files, waarbij er weer verschillen - zijn tussen de .REL files van versie 1.1 en versie 1.2: - - CK.REL: De zogenaamde kernel, deze code wordt uitgevoerd bij - het opstarten van een C programma. De kernel onderzoekt de - command line en springt vervolgens naar de routine "main" - toe. Bij versie 1.1 wordt bij het onderzoeken van de command - line tevens gecontroleerd op de symbolen > (redirection) en - | (pipelining), dit omdat MSX-DOS 1 geen redirection en - pipelining ondersteunt, terwijl een aantal C toepassingen - hier wel gebruik van maken omdat C uit de UNIX wereld komt - waar redirection en pipelining zo ongeveer zijn uitgevonden. - Versie 1.2 controleert hier niet meer op omdat MSX-DOS 2 dit - zelf doet. - - CRUN.REL: Hier zitten een aantal routines in die nodig zijn - bij een C programma, zoals het vermenigvuldigen, delen en - vergelijken van 16 bits getallen. Als er in de source file - bijv. staat: - - { - int a,b,c; - a = 3; b = 4; - c = a * b; - } - - dan maakt de compiler ervan: - - ld hl,3 - ld de,4 - call ?MULHD - - De routine MULHD is dan te vinden in CRUN.REL. Er is hierbij - geloof ik geen verschil tussen de 2 CRUN versies. - - CEND.REL: In deze file bevind zich het label @endx@ zodat - eventuele interne routines uit CK en CRUN weten tot waar het - programma loopt. - - CLIB.REL: Dit is de echte C library waar de standaard - functies in zitten. Hierbij zijn er wezenlijke verschillen - tussen versie 1.1 en versie 1.2, de eerste werkt bij de file - in/out namelijk overal met FCB's, terwijl de tweede overal - met de file handles van MSX-DOS 2 werkt. Het is hierom ook - belangrijk dat van CK.REL en CLIB.REL de goede versies bij - elkaar worden gebruikt, dit omdat CK een aantal standaard - devices opent voor functies zoals printf(). Bij CK 1.1 en - CLIB 1.1 worden hier dus FCB's voor gebruikt terwijl CK 1.2 - en CLIB 1.2 alles met de file handles doen. CK 1.2 - controleert tevens de DOS-versie zodat C programma's die - gelinkt zijn met deze versie een foutmelding geven als ze - onder MSX-DOS 1 worden opgestart. - - Behalve deze library's worden ook nog een aantal header - files meegeleverd waar alle relevante types in worden - gedefinieerd. Bij versie 1.2 zijn de header files een stuk - verder opgesplitst dan bij versie 1.1. Tevens zijn de - definities van sommige types veranderd, zo is bijv. het type - FILE veranderd omdat de routines uit CLIB hier andere - informatie in opslaan. Het is daarom belangrijk dat de - versie van de header-files overeenkomt met de versie van de - library's! - - Alex Wulms diff --git a/future_disk/15/Looplichtje.md b/future_disk/15/Looplichtje.md new file mode 100644 index 0000000..47052e2 --- /dev/null +++ b/future_disk/15/Looplichtje.md @@ -0,0 +1,50 @@ + Looplichtje + + ���� + ���� + ���� + ���� + + Op deze disk zal je een schema van een looplichtje vinden. + Alweer zo iets doms? Ja, alweer. Dit is weer zo'n normaal + looplichtje, alleen deze versie heeft wat minder onderdelen + nodig dan de al bestaande uitvoeringen. Het origineel komt van + Albert Huitsing en is daarna enigszins gewijzigd door mij. + Als het beestje af is moet het mogelijk zijn om via de + computer de acht ledjes onafhankelijk aan en uit te zetten. + Natuurlijk hoeven het geen ledjes te zijn. Door 5v relais + aan te sluiten is een heleboel mogelijk. Wat dacht je van + een RC Autootje aan je computer of al je lampen aan of uit + via je computer?(NvdR: eeeeuuhh??!?) + + Wat heb je nodig? + + 1 IC : MB74LS164 (of een andere 74164) + 8 5volts ledjes (Kleur naar keuze) + 1 Experimenteer printje (ca. 5x5cm) + 1 Vier aderige flatcable (ca. 15cm) + 1 9-polige Sub_D connector male (Joystick connector) + 1 Pakje Drum met vloei (Optioneel) + een soldeerbout, tin, en stalen zenuwen bij het uittesten. + + Als je dat allemaal hebt gekocht kun je de file PRINT.LDR + runnen om het printje te bekijken. Het afgebeelde is heir de + koperzijde. De betekenis van de nummers is als volgt: + 1 staat voor TRiGger(1) + 2 is de GRND + 3 TRG(2) + 4 staat voor 5 Volt + + + + In de file LOOPLICH.BAS staat hoe je het geheel kan besturen. + Op de volgende FutureDisk zal je het programma LED_Tracker + vinden waar mee je in een patern/position editor een sequence + kan maken om de leds aan en uit te zetten(No, thats no + nonsense!)(NvdR: believing that guy is one big mistake!). + Anyway... soldeer ze! + + Uiteraard is de FutureDisk niet aansprakelijk voor eventuele + schade aan computer/randapparatuur. (Lekker opstekertje h�?) + + Tobias + diff --git a/future_disk/21/Ledjes.md b/future_disk/21/Ledjes.md new file mode 100644 index 0000000..65dd2d5 --- /dev/null +++ b/future_disk/21/Ledjes.md @@ -0,0 +1,69 @@ +Keizer maakt nooit wat af. Dat is een statement. Keizer probeert dit statement in deze tekst eens en voor altijd tot het verleden te verdoemen + + + UNFINISHED BUSINESS... + + ���� + ���� + ���� + ���� + + + De vorige keer had ik al wat zitten zemelen over de ledjes in + de Turbo-R. Nu was ik echter druk bezig met een poker-spel dat + ik op 't laatste moment toch niet af kreeg zodat ik het pro- + grammaatje dat erbij hoorde op 't laatste moment toch niet af + kreeg. Nu dus maar even in een text-file hoe je alle leds moet + aansturen. Om maar gelijk met het slechte nieuws te beginnen, + twee leds vallen sowieso al af. De power led en de Renshaturbo + led. Deze zijn beide hardware-matig en dus niet aan te sturen. + De FDD led valt eigenlijk ook al af. Hij is wel aan te sturen + maar met mijn gebrekkige kennis van het programmeer vak dus + not sorry 'bout that. Misschien dat Smael dit weet maar + ik dus niet... Blijven er vier leds over: + CAPS, KANA, PAUSE en R800 + + + CAPS: + + DEFUSR=&H0132:A=USR(x) ' X=0, UIT. X<>0, AAN. + + + KANA: (ALLEEN IN MC) + + LD IX,$0135 + CALL $015F + RET + + + PAUSE: + + OUT (&HA7),&B0000001 + + + R800: + + OUT (&HA7),&B1000000 + + + Natuurlijk kan je MC data even in WB-ASS2, juist ja.. die + assembler die elk zichzelf-respecterend-mens heeft, DISen om + de opcodes even weg te poken en te USRen. Dat lousy excuse + for een intro demo dat deze keer op de FD staat(NvdR: + herstel; de volgende keer op de FD staat) gebruikt de + Turbo-R leds al zodat dat het enorme gemis van de vorige keer + weer een beetje gecompenseerd wordt. Well, I'm getting a bit + vague here coz it's late so I'll take a little coffee break + now and type some more later. C YA!!! + + Tobias 'No remark this time' Keizer... + + Whoops, voor ik 't vergeet... Dat R800 gemier van de vorige + keer was ook niet goed... Het stukje MC + Basic dat ik de + eerste keer geef was zoals 't hoorde. Niks geen subrom of zo. + Ik was gewoon even verward omdat die rountine dus geen A=USR + (130) slikt als je die USR op &H0180 hebt gezet. Waarom ie dat + niet wil weet ik niet, maar met dat kleine stukje MC werkt het + allemaal wel... + + Succes, Keizer... diff --git a/future_disk/21/Recursie.md b/future_disk/21/Recursie.md new file mode 100644 index 0000000..0781b80 --- /dev/null +++ b/future_disk/21/Recursie.md @@ -0,0 +1,128 @@ +Dit is alweer het negende deel van de PASCAL cursus door de enige echte Jeroen Smael + + Recursie + + + ���� Ja, je leest het goed, dit deel gaat over recursie. Na + ���� mij weer een nummer gemist te moeten hebben hier weer + ���� een deel van de o zo populaire PASCAL cursus. Ik zal de + ���� vraag waarom er vorige keer geen PASCAL cursus was snel + beantwoorden. Ik heb werk en dus weinig tijd (al + begrijpt Koen dat niet, maar die is nog maar student)(NvdR: + scuze me?). Ik zal verder niemand nog langer vervelen met + mijn priv� leven (daar heeft trouwens ook niemand iets + mee te maken, maar dat terzijde)(NvdR: nee, dat priv�-leven + van jou is ook zooooo spannend, Smael). + + Recursie (2) + + Wat is recursie? Recursie is (letterlijk) herhalen. Wat kun je + ermee? Heel veel, maar dat zal (hopelijk) nog wel duidelijk + worden. Een klassiek voorbeeld van recursie is + machtsverheffen. + + Machtsverheffen + + Wat is machtsverheffen? + +x^n = x^(n-1)*x +x^(n-1) = x^(n-2)*x +x^(n-2) = x^(n-3)*x + + Ok, je begrijpt het nu wel. De vraag is alleen wanneer stop ik + (terminate). Ik stop als (n-?) gelijk aan 0 is. Waarom? Als + (n-?) gelijk aan nul is dan krijg ik x^0 en dat is ALTIJD 1. + De functie ziet er dan als volgt uit: + + PROCEDURE Macht2(n : integer) : integer; + + BEGIN + IF n=0 THEN + Macht2=1 + ELSE + Macht2=Macht2(n-1)*2 + END; + + Bovenstaand is om elke willekeurige (positieve) macht van 2 te + berekenen (dat zit immers niet standaard in PASCAL). + Bijzonderheden zijn dat de functie zichzelf aanroept + (Macht2=Macht2(n-1)*2). Dat zou eigenlijk niet kunnen, omdat + de functienaam eigenlijk alleen aan de linkerkant van het = + teken mag staan (voor een toewijzing). Maar mag in dit geval + wel. + + Is dit alles? + + Nee, dit is nog lang niet alles, maar het volgende (en tevens + laatste) voorbeeld is wel iets lastiger. Waarom? Omdat dit een + voorbeeld van backtracking is. Wat is Backtracking? + Backtracking wordt gebruikt voor zoek algoritmen. + + Backtracking + + Stel je staat in een doolhof. Wat doe je? Je gaat zoeken + natuurlijk, maar hoe? Als een kip zonder kop lijkt me niet erg + verstandig, want dan kom je nooit waar je wil zijn (de + uitgang). Dus ga je systematisch zoeken. Maar hoe doe je + dat? Als je veel tijd hebt (en wat heb je anders in een + doolhof) dan ga je altijd rechts. Is dat niet meer mogelijk, + dan ga je rechtdoor. Gaat dat niet meer, dan ga je links. Gaat + dat niet meer, dan ga je terug tot de plaats waar je als + laatste een keus moest maken en doet daar hetzelfde. Op die + manier kom je waar je wezen moet (bij de uitgang). Wat je + natuurlijk niet moet doen (maar wat ik vergeten ben te zeggen) + is over je eigen weg lopen (dus als je er al geweest bent, dan + ga je niet verder, omdat je anders in een kring gaat lopen). + + Implementatie + + Ik ga de pseudo code van de implementatie geven, zodat je die + zelf uit kunt werken. Je moet dan wel zelf de hele + datastructuur opzetten, want dat doe ik niet voor je. Hier + gaat 'ie: + + PROCEDURE ZoekUitgang(Doolhof , Locatie , Gevonden); + + BEGIN + IF Locatie is buiten THEN + Gevonden = TRUE + ELSE + BEGIN + IF mogelijk naar rechts THEN + ZoekUitgang(Doolhof(markeer Locatie) , + Locatie + 1 naar rechts , Gevonden); + IF NOT Gevonden & mogelijk naar voren THEN + ZoekUitgang(Doolhof(markeer Locatie) , + Locatie + 1 naar voren , Gevonden); + IF NOT Gevonden & mogelijk naar links THEN + ZoekUitgang(Doolhof(markeer Locatie) , + Locatie + 1 naar links , Gevonden); + END; + END; + + Dat is alles. Hier horen natuurlijk een paar opmerkingen bij + en wel de volgende: + - Doolhof is een array waar de doolhof in staat en tevens of + je er geweest bent. + - Locatie is je 'X en Y' positie in de doolhof + - mogelijk is een functie die aangeeft of je die richting uit + mag (dit kun je ook de de procedure ZoekUitgang laten doen, + aangezien in een muur ook niet buiten is). + - markeer locatie is in Doolhof aangeven dat je er geweest + bent (dat moet je daarna wel weer verwijderen, anders zoek + je niet alles af). + + Wat moet ik zeker weten + + Wat je zeker moet weten is dat de MSX Turbo PASCAL v3.3 geen + recursie aankan. "Wat, geen recursie, waarom heb je ons dit dan + allemaal verteld?" + Omdat je recursie wel aan kunt zetten. Hoe? Door de $A+ optie + te gebruiken. Vergeet dit niet, anders klopt er niets van je + baksels (zelfs het machtsverheffen werkt dan al niet). + + Dat was het, + + Jeroen Smael + + C YA L8R!! diff --git a/future_disk/27/Rotatie.md b/future_disk/27/Rotatie.md new file mode 100644 index 0000000..ef14746 --- /dev/null +++ b/future_disk/27/Rotatie.md @@ -0,0 +1,329 @@ +Jan-Willems brein maakt overuren... + + ROTATIE (1) + + ���� + ���� + ���� + ���� + + + + Een tijd terug heeft Martijn ten Brink ooit een puik stukje + programmeerwerk afgeleverd genaamd de rotator. Hiermee was + het mogelijk om een plaatje over een bepaalde hoek te rote- + ren. Martijn programmeerde het in KUN-basic. Omdat dit ook + in machinecode kan (en dan iets sneller is) zal ik in de + nu volgende text de formule die de rotatie beschrijft uitleg- + gen en jullie voorzien van een brokje code waar de hersenen + weer over gepijnigd kunnen worden. + + + DE FORMULE + + De rotatieformule luidt als volgt: + + + X2 cos a sin a X1 - X0 X0 + = * + + Y2 -sin a cos a Y1 - Y0 Y0 + + + Hier kunnen jullie natuurlijk niks uit opmerken, maar voor + degenen die weten wat matrices zijn en op de juiste plaatsen + wat verticale strepen plaatsen, zien zij dat [X2 Y2]t gevormd + worden door de vermenigvuldiging van de 2*2 matrix, die met + de sinusjes, met de 2*1 matrix, die met de X1 etc. plus de + 2*1 matrix [X0,Y0]t. We kunnen dit natuurlijk ook + uitschrijven, dan krijgen we: + + X2 = ( cos a) * (X1 - X0) + (sin a) * (Y1 - Y0) + X0 + Y2 = (-sin a) * (X1 - X0) + (cos a) * (Y1 - Y0) + Y0 + + Voor de meesten van u is dit al iets beter leesbaar. + + Uiteraard is dit een geniale formule, maar euh, wat roteert + er nu en hoe ???? + + DE PARAMETERS + +OK, het antwoord hierop luidt: + +X2,Y2: zijn de eindcoordinaten van X1,Y1 +X1,Y1: zijn de coordinaten van de pixel die je wilt + roteren +X0,Y0: zijn de coordinaten van het centrum waaromheen je + wilt roteren +a: is de hoek waarover geroteerd wordt + + Klinkt interessant, maar zonder tekeningetje of voorbeeld + wordt het niet echt verduidelijkt. Een tekeningetje kan deze + (geniale, hemelsche, ridicule, smaelse) textroutine niet aan, + dus een voorbeeld. + + Stel wij willen op screen 5 (256*212) het beeld een kwartslag + naar rechts roteren. Dat is dus over een hoek van 90 graden. + We draaien om de as van het beeld, dus die is het middelpunt + van het scherm (128,106). Nu rekenen we voor punt (0,0) uit + waar ie terecht komt. + + De parameters waren dus: + + a: de hoek = 90 graden + X0,Y0 het centrum van de rotatie: (128,106) + X1,Y1 het punt dat geroteerd moet worden + + Er geldt nu: + + X2 = -1 * (0 - 128) + 0 * (0 - 106) + 128 = 256 + Y2 = 0 * (0 - 128) + 1 * (0 - 106) + 106 = 0 + + En inderdaad, dit zijn de coordinaten waarop punt (0,0) te- + recht moet komen. + + HET PROGRAMMA + +Kijken we nog eens naar de formule: + + X2 = ( cos a) * (X1 - X0) + (sin a) * (Y1 - Y0) + X0 + Y2 = (-sin a) * (X1 - X0) + (cos a) * (Y1 - Y0) + Y0 + +Alles wat we nodig hebben, zijn: +- een subroutine om cos a en sin a uit te rekenen +- een (snelle) vermenigvuldigings routine +- nog wat vram lees en schrijf rommel + + Om cos a en sin a te berekenen kun je ingewikkeld doen en effe + de machtreeks van beiden door je Z80 laten uitrekenen, maar + aangezien dit veel (en als ik zeg veel, dan bedoel ik veel) + tijd kost, is het simpeler om van te voren een tabel aan te + maken met daarin genoeg waarden om een mooie rotatie te + krijgen (zo om en nabij de 360 dus :) ). + Het leuke van sinus en cosinus is, dan sin a = cos (a - 90). + als ik dus een cosinustabel heb met 360 entries, kan ik door + er de nog 90 waarden aan toe te voegen gelijk de sinuswaarden + uithalen. De tijd die dus nu nodig is om een sinuswaarde op te + halen is minimaal. De volgende routines zouden al werken: + + cosinus: + ; pre: in HL de hoek. + ; post: A = cos (HL) + ld de,tabel + add hl,de + ld a,(hl) + ret + sinus: + ; pre: in HL de hoek + ; post: A = sin (HL) + ld de,tabel+90 ; uitgaand van een 360-entry tabel + add hl,de + ld a,(hl) + ret + + De werking hiervan spreekt voor zich. + Een nadeel hieraan is de nauwkeurigheid van de sinus. Zoals + u allen weet geeft de sinus-functie waarden tussen de -1 en de + 1 af. In BASIC of een hogere programeertaal is dit geen + probleem, maar in code kunnen we niet met de komma werken en + ziet de processor een min toch echt voor iets anders aan. + Een oplossing hiervoor is om of 2 bytes te gebruiken, of het + bereik van onze z80 sinus tussen de -64 en de +64 te kiezen. + Dus als je rekenapparaat 1 geeft, geeft onze routine een 64 + uit. Waarom 64, waarom niet 128? Het probleem hierbij is dat + we graag met plusjes en minnen werken bij sinusfunctie en dat + binnen een byte +128 niet te realiseren valt, we zouden dan de + nul 2 keer definie�ren. + +LEES VERDER IN TEKST (2) + Het brein van Jan-Willem maakt weer overuren... + + ROTATIE (2) + + ���� + ���� + ���� + ���� + + + + We gaan verder waar Jan-Willem gebleven was... + + + Ook hebben we nog wat rappe vermenigvuldigings routines nodig. + Het beste formaat is een routine die onze 8-bits sinuswaarde met + de 16-bits waarde van X1-X0 vermenigvuldigd en het resultaat + afleverd in een 16-bits getal. + De minimale waarde die we kunnen krijgen is -64 * 256 = -16384 + en het maximum is 64 * 256 = 16384. + Om rap te kunnen vermenigvuldigen slaan we het boekje + Machinetaal Z80 effe open en tikken daaruit over: + + multiply: + ; pre: HL bevat 2 complement X1 - X0, a bevat sinwaarde + ; post: HL = HL * A + ; comment: de vermenigvuldiging is signed + push hl + exx + pop de + ld c,a + and a + ld b,0 + jp p,positief + dec b + positief: + ld hl,0 + exx + ld b,16 + multilus: + exx + sla l + rl h + sla e + rl d + jp nc,geenoptelling + add hl,bc + geenoptelling: + exx + djnz multilus + exx + push hl + exx + pop hl + ret + + Zoals jullie zien is deze vermenigvuldiging mooi signed. + Hij kan misschien nog wel wat sneller, maar ik ben er + tijdelijk wat lui voor om de snelst werkende te maken. + Daarvoor verwijs ik jullie naar Alex Wulms of zo. + + Maar goed, nu we beide routines hebben, kunnen we het + mainframe van de rotator gaan cre�ren. + + HET MAINFRAME + + We kijken weer es naar de formule: + + X2 = ( cos a) * (X1 - X0) + (sin a) * (Y1 - Y0) + X0 + Y2 = (-sin a) * (X1 - X0) + (cos a) * (Y1 - Y0) + Y0 + + onze code wordt dus: + + start: + call leespixel + ld (inhoud),a + + ld a,(hoek) + call cosinus + + ld hl,X1 + ld de,X0 + and a + sbc hl,de + + call multiply + + push hl + + ld a,(hoek) + call sinus + + ld hl,Y1 + ld de,Y0 + and a + sbc hl,de + + call multiply + + pop de + + add hl,de + + ld de,X0 + add hl,de + + call convert + ld (xcoor),a + + + ld a,(hoek) + call sinus + + neg + + ld hl,X1 + ld de,X0 + and a + sbc hl,de + + call multiply + + push hl + + ld a,(hoek) + call cosinus + + ld hl,Y1 + ld de,Y0 + and a + sbc hl,de + + call multiply + + pop de + + add hl,de + + ld de,Y0 + add hl,de + + call convert + ld (ycoor),a + + ld hl,(xcoor) + ld a,(inhoud) + call putpixel + ret + + leespixel: + ; pre: niks + ; post: a= inhoud gelezen pixel + ret + putpixel: + ; pre: l=xcoor,h=ycoor,a=inhoud pixel + ; post: pixeltje op het scherm + ret + convert: + ; pre: HL bevat X2 of Y2 + ; post: A bevat goede co�rdinaatwaarde + ld b,6 + convertloop: + sra h + rr l + djnz convertloop + ld a,l + ret + + Na het lezen hiervan vallen U enkele dingen meteen op: +- de code is geniaal! +- de heer Van Helden is weer eens te lui om wat routines te + coden; +- wat doet convert nu weer? + +Tsja, ik zal enkel een antwoord geven op de laatste vraag. +Het zit namelijk zo. Omdat wij de sinus een bereik hebben ge- +geven van (-64,64), zitten onze waarden in het bereik (-256*64, +256*64). Om dit schoonheidsfoutje te verhelpen moeten we HL +nog 6 keer naar rechts schuiven. Om op clipping te controleren +hoef je enkel te kijken of na de routine convert H ongelijk aan +0 is. Is dit namelijk het geval, dan probeert je Z80 op een +negatieve x of y coordinaat iets weg te dumpen. + +Op de disk staan de routines die ik gegeven heb in de file +"rotator.gen". Misschien heeft iemand zin om er iets mee te +doen. Oh ja, de sinustabel maak je gewoon in basic en schrijf +je dan weg naar disk. + +Ik wens eenieder die met deze routines aan de slag gaat veel +plezier. + +Jan-Willem van Helden diff --git a/future_disk/34/mathpack.md b/future_disk/34/mathpack.md new file mode 100644 index 0000000..075182e --- /dev/null +++ b/future_disk/34/mathpack.md @@ -0,0 +1,195 @@ +Arjan vertelt jullie iets over dingen waar ik dus effe geen hol over kan zeggen... + DE MATHPACK + + + De MathPack is een verzameling routines voor het gebruik van + gebroken getallen. Deze routines vormden eerst geen + standaard, maar omdat de routines in alle MSX1-roms op + dezelfde plek zaten, hebben de programmeurs van de MSX2-roms + (en 2+/Turbo-R) ze op die plek gehouden en is het dus een + standaard geworden. De informatie over de MathPack heb ik + verdeeld over 2 delen. De eerste tekst gaat over de opbouw + van de getallen en de tweede gaat over de functies van de + MathPack. + + + OPBOUW + + De MathPack kent drie soorten getallen, namelijk integers, + enkele precisie en dubbele precisie. Deze getallen zijn + hetzelfde als in BASIC. + + De integers zijn als volgt opgebouwd. De eerste 2 bytes zijn + ongebruikt en de volgende 2 bytes geven het getal aan in de + gebruikelijke volgorde, dus lowbyte-highbyte. Een voorbeeld: + 4942 wordt bij de MathPack: 0 0 78 19 + + Getallen van enkele en dubbele precisie worden heel anders + opgebouwd. Bij beide getaltypen bevat het eerste byte het + teken en de exponent. De rest van de bytes (3 bij enkele en + 7 bij dubbele precisie) geeft het getal aan, ook wel de + mantisse genoemd. Schematisch ziet dit er als volgt uit: + + +/- 0.MANTISSE +/- EXPONENT + + Als de exponent positief is, moet de mantisse naar rechts + geschoven worden en als de exponent negatief is, moet de + mantisse naar links geschoven worden. Een voorbeeld: + -30 wordt opgeslagen als -0.3 E+2, de exponent is dus +2 en + de mantisse is 3. + + De mantisse wordt opgeslagen in het zogaamde Binairy Coded + Decimal-formaat, BCD. Dit houdt in dat ��n byte 2 decimale + getallen op kan slaan, maar dat wordt dan wel hexadecimaal + gedaan. Het getal 65 wordt dus opgeslagen als #65. De reden + hiervoor is dat de computer zo sneller kan rekenen. + + Dan het teken. Het teken staat in bit 7 van het eerste byte. + Is deze 1, dan is het getal negatief, is het 0, dan is het + positief. + + De exponent beslaat bit 6-0 van het eerste byte. Bit 6 bevat + het teken van het exponent. Is deze een 1, dan is de + exponent positief, is het een 0, dan is de exponent + negatief. Als de exponent negatief is, moeten de bits + omgedraait worden en dan moet er 1 bij opgeteld worden. + Verwarrend? Ja, inderdaad, dat is het. Het kan iets + simpeler. Als de exponent negatief is, trek het dan af van + 64 en je krijgt ook het goede resultaat. + + Een paar voorbeelden: + + Stel, het eerste byte is #C1, binair dus &B11000001. Bit 7 + is 1, dus is het getal is negatief. Bit 6 is 1, dus de + exponent is positief. Bits 5-0 geven de exponent aan, en dat + is in dit geval dus 1. + + Stel, het eerste byte is #0A, binair dus &B00001010. Bit 7 + is 0, dus het getal is positief. Bit 6 is 0, dus de exponent + is negatief. Bits 5-0 moeten dan omgeklapt worden, dus bits + 5-0 worden &B110101. Dan moet er 1 bij opgeteld worden, dus + dat wordt &B110110 en de exponent is dus 54. + + Als het eerste byte 0 is, geeft dat aan dat het getal 0 is. + + Nu kun je dus een getal van enkele/dubbele precisie opslaan. + Hier komen nog een paar voorbeelden die laten zien hoe + getallen van dubbele precisie moet opslaan (om het te + verduidelijken). + + 5 wordt opgeslagen als #41 5 0 0 0 0 0 0 + -500 wordt opgeslagen als #C3 5 0 0 0 0 0 0 + 123.123 wordt opgeslagen als #43 #12 #31 #23 0 0 0 0 + 50E+10 wordt opgeslagen als #6C #50 0 0 0 0 0 0 + 50E-10 wordt opgeslagen als #38 #50 0 0 0 0 0 0 + + + FUNCTIES + + Nu je weet hoe de getallen opgeslagen moeten worden, is het + tijd voor de functies van de MathPack. De functies maken + gebruik van drie adressen, namelijk: + + Naam Adres Lengte Functie + DAC #F7F6 16 Decimale ACcuumulator (accu 1) + ARG #F847 16 ARGument voor bewerking (accu 2) + VALTYP #F663 1 Variabele type + 2 = Integer + 4 = Enkele precisie + 8 = Dubbele precisie + + Zoals je ziet, is de lengte van de DAC 2 keer zo groot als + een getal van dubbele precisie. Het getal moet in de eerste + 8 bytes gezet worden, de rest van de bytes worden gebruikt + als werkruimte, dus zet hier niets in! Dit geldt natuurlijk + ook voor ARG. + + De functies zijn onder te verdelen in drie groepen, namelijk + de gewone functies, de transcedente functies en de overige + functies. + + + GEWONE FUNCTIES + + Deze functies werken alleen met getallen van dubbele + precisie, tenzij het anders is aangegeven. Verder is het wel + duidelijk wat ze doen. Hier komt een lijstje met de + functies. + + Naam Adres Functie + DECSUB #268C DAC = DAC - ARG (aftrekken) + DECADD #269A DAC = DAC + ARG (optellen) + DECMUL #27E6 DAC = DAC * ARG (vermenigvuldigen) + DECDIC #289F DAC = DAC / ARG (delen) + DECNRM #26FA DAC = NORM(DAC) (normaliseren (=voorloopnullen + weghalen)) + DECROU #273C DAC = ROUND(DAC) (afronden) + SNGEXP #37C8 DAC = DAC ^ ARG (machtsverheffen) + (enkele precisie!) + DBLEXP #37D7 DAC = DAC ^ ARG (machtsverheffen) + + + TRANSCEDENTE FUNCTIES + + Deze functies kunnen alleen overweg met getallen van enkele + en dubbele precisie. Zet VALTYP daarom op de juiste waarde, + zodat de berekening goed wordt uitgevoerd. Verder spreken de + functies wel voor zich. + + Naam Adres Functie + COS #2993 DAC = COS(DAC) (cosinus) + SIN #29AC DAC = SIN(DAC) (sinus) + TAN #29FB DAC = TAN(DAC) (tangens) + ATN #2A14 DAC = ATN(DAC) (arctangens) + LOG #2A72 DAC = LOG(DAC) (natuurlijke logaritme) + SQR #2AFF DAC = SQR(DAC) (vierkantswortel) + EXP #2B4A DAC = EXP(DAC) (exponent) + RND #2BDF DAC = RND(DAC) (random getal) + + + OVERIGE FUNCTIES + + Deze functies hebben te maken met het teken van het DAC. + Eerst weer even een lijstje, daarna de uitleg. + + Naam Adres Functie + SIGN #2E17 A = SGN(DAC) (Teken van DAC naar accu) + ABSFN #2E82 DAC = ABS(DAC) (Maak DAC positief) + NEG #2E8D DAC = -DAC (Verander teken) + SGN #2E97 DAC = SGN(DAC) (Teken van DAC naar DAC) + + SIGN bepaalt het teken van DAC en stopt het in de + accumulator. Als de DAC 0 was, dan wordt A ook 0, als de DAC + negatief was, wordt A #FF en als de DAC positief was, dan + wordt A 0. Deze functie werkt alleen met getallen van + dubbele precisie. + + ABSFN maakt de DAC positief. Deze functie werkt met alle + variabelentypes. Alleen bij integers is er iets vreemds aan + de hand. Als de DAC #8000 was, dus -32768, zou de absolute + waarde +32768 zijn, maar dat past niet in een integer. + Daarom wordt het getal omgezet naar enkele precisie. + + NEG verandert het teken van de DAC, dus 10 wordt -10 en -20 + wordt 20. Deze functie werkt met alle variabelentypes. Bij + integers is hier weer hetzelfde aan de hand als bij de + functie ABSFN. + + SGN tenslotte doet hetzelfde als SIGN, maar nu komt het + teken in de DAC. Het resulaat is een integer met de waarde 0 + als de DAC 0 was, 1 als de DAC positief was en #FFFF als de + DAC negatief was. + + In de MathPack zitten nog meer functies, maar daar heb ik + (nog) geen documentatie over. Misschien komen deze een + andere keer aan bod. + + Oh ja, de foutafhandeling van de MathPack verloopt via + BASIC. Als je een verkeerde variabeletype gebruikt, kom je + dus terug in BASIC. Dit kun je voorkomen door de hook H.ERRO + (#FFB1) om te buigen, maar beter is het natuurlijk om + gewoon geen fouten te maken. + + +Arjan Bakker + diff --git a/future_disk/35/Datacompressie.md b/future_disk/35/Datacompressie.md new file mode 100644 index 0000000..38c465e --- /dev/null +++ b/future_disk/35/Datacompressie.md @@ -0,0 +1,72 @@ +Hmmm....nu wordt het moeilijk...ik zeg niks... + DATACOMPRESSIE + + ���� + ���� + ���� + ���� + + + Lang, heel lang geleden stonden er wat teksten over + datacompressie op de FD (ik meen zo rond FD 20). Aangezien + er veel manieren zijn om data te crunchen, is hier weer een + tekstje over een manier om data te crunchen die in bepaalde + gevallen best wel handig kan zijn. + + De compressiemethode die ik nu ga bespreken, heeft voor + zover ik weet geen naam, maar dat maakt op zich niet uit. De + methode is snel te implementeren en het (de)crunchen gaat + aardig snel. + + De compressiemethode gaat ervan uit dat een byte in zekere + mate herhaald wordt. Per byte wordt onderzocht of de byte + hetzelfde is. Als dat zo is, wordt er een 0 weggeschreven + naar een bitstream. Als het niet gelijk was, wordt er een 1 + weggeschreven en de byte zelf. Bij teksten bijvoorbeeld komt + de spatie heel vaak voor. Hier wordt dus de spatie met 1 bit + opgeslagen en de overige bytes met 9 bits. Om alles + duidelijk te maken, komt hier een voorbeeld: + + Stel, we hebben de volgende reeks bytes: + + 0 10 25 10 4 6 12 10 50 10 10 + + De 10 komt het meeste voor in deze reeks. Telkens als er 10 + staat in de reeks, dan schrijven we een 0 weg en anders + schrijven we een 1 weg gevolgd door de byte zelf. Hier komt + eventjes de gecrunchde data (links in bytes, rechts in + bits): + + 0 = 1 00000000 + 10 = 0 + 25 = 1 00011001 + 10 = 0 + 4 = 1 00000100 + 6 = 1 00000110 + 12 = 1 00001100 + 10 = 0 + 50 = 1 00110010 + 10 = 0 + 10 = 0 + + De lengte van de ungecrunchde data was 11 bytes, dus 88 + bits. De gecrunchde data is echter maar 59 bits groot. + Natuurlijk moet je ook weten welke byte er met een 0 bedoeld + wordt, dus dat kost weer 8 bits extra, maar de data wordt + nog altijd kleiner. + + + VARIATIES + + Er zijn nog veel variaties op deze methode te verzinnen. Bij + tekeningen bijvoorbeeld kun je voor ��n hele tekening een + vaste byte nemen, maar je kunt het ook per lijn doen en dat + is waarschijnlijk wel efficienter. Deze compressie-methode + is alleen handig bij tekstdata en tekeningen, want daarin + zitten veel dezelfde bytes. In programma's zijn er ook wel + bytes die vaak voorkomen, maar die komen dan niet vaak + genoeg voor om deze goed op deze manier te kunnen inpakken. + (Nvdr: euhmmm...Arjan...zou je dit voor de volgende keer + eens wat meer kunnen uitdiepen?) + +Vincent diff --git a/future_disk/42/lijntjes.md b/future_disk/42/lijntjes.md new file mode 100644 index 0000000..d241d50 --- /dev/null +++ b/future_disk/42/lijntjes.md @@ -0,0 +1,106 @@ +Lijntjes zijn heel cool, zo kun je van 4 lijntjes een rechthoek of een vierkant of een parallellogram (ofzo) maken, lijntjes zijn goed... + + LIJNTJES + + + E�n van de lastigste VDP-commando's is wel het line- + commando. Het VDP line-commando werkt namelijk heel anders + dan het BASIC line-commando. In BASIC kun je lekker + makkelijk het start- en eindpunt opgeven, maar de VDP wil + naast het beginpunt ook de lengte van de lijn weten, en de + richting. Okay, als je weet hoe het moet, is ook het line- + commando een makkelijk commando, maar anders kan het je + zeker grijze haren bezorgen. + + Het makkelijkste om op te geven is het beginpunt van de + lijn; deze kunnen direct in VDP-register 36/37 (X) en 38/39 + (Y) gezet worden. + + Moeilijker is de lengte van de lijn. Om deze te kunnen + bepalen, moet je eerst de betekenis van register 45 weten. + Deze is als volgt: + + bit: 7 6 5 4 3 2 1 0 + 0 MXC MXD MXS DIRY DIRX EQ/NEQ MAJ/MIN + + Ik zal hier alleen even de betekenis van de benodigde bits + uitleggen. + + DIRY: 1: lijn gaat omhoog, 0: lijn gaat omlaag + DIRX: 1: lijn gaat naar links, 0: naar rechts + + MAJ/MIN: 1: Y is belangrijkste richting + 0: X is belangrijkste richting + + Nu kunnen we de lengte en de richting van de lijn bepalen. + Om de X-richting te bepalen trek je het eindco"rdinaat van + het begin-co"rdinaat. Als het resultaat positief is, dan + moet DIRX geset worden. Als het resultaat negatief is, dan + moet het weer positief gemaakt worden (NEG) en moet DIRX + gereset worden. Tot slot zet je het resultaat in register + 40/41 (NX).Hetzelfde verhaal geldt voor de Y-richting, + alleen moet je nu DIRY en register 42/43 (NY) invullen. + + En dan het vreemdste van het line-commando. Als NY groter + dan NX is, dan moeten deze twee waarden omgewisseld worden + en moet MAJ/MIN geset worden. Waarom dit zo gedaan moet + worden weet ik ook niet, maar ja, het moet maar. + + Oh ja, voordat ik het vergeet, de lijnkleur moet in register + 44 komen en register 46 moet met het juiste commando gevuld + worden. En dat commando is (zonder logische operaties) + &b01110000. De logische operatie moet op de laagste 4 bits + ingevuld worden, maar dat weet je waarschijnlijk wel (en + anders lees je nu de verkeerde tekst). + + Tot slot komt hier nog even een source van een line-routine. + + ;In: H: SX + ; L: SY + ; D: DX + ; E: DY + ; C: kleur + + line: ld a,c + ld (color),a ;kleur + + ld a,h + ld (dx),A ;begin X + + ld c,4 ;dir X = links + sub d ;bepaal lengte X-richting + jr nc,line1 ;positief = naar links + ld c,0 ;dir X = rechts + neg ;maak positief + line1: ld b,a ;bewaar in B + LD (nx),A ;en vul in + + ld a,l + ld (dy),a ;begin Y + + set 3,c ;dir Y = omhoog + sub e ;bepaal lengte Y-richting + jr nc,line2 ;positief = omhoog + res 3,c ;dir Y = omlaag + neg ;maak positief + line2: ld (ny),a ;en vul in + cp b ;welke richting is groter? + jr c,line3 ;X>Y, dan is alles goed + set 0,c ;Y is belangrijkste richting + ld (nx),a ;vul Y in NX-register in + ld a,b + ld (ny),a ;vul X in NY-register in + + line3: ld a,c + ld (data),a ;vul dirx/diry/ maj/min in + ld a,%01110000 + ld (command),a ;vul line-commando in + call copy ;voer commando uit + ret + + De rest van de source is niet interessant, want die dient + voor het sturen van de juiste data naar de VDP. Voor de + volledigheid staat de source ook op deze FD onder de + logische naam LINE.GEN. + +Arjan diff --git a/sunrise_special/1/r800.md b/sunrise_special/1/r800.md new file mode 100644 index 0000000..feeedbf --- /dev/null +++ b/sunrise_special/1/r800.md @@ -0,0 +1,857 @@ +# D E R 8 0 0 + + +## I N L E I D I N G + +Het hart van de MSX turbo R wordt gevormd door een nieuwe +processor: de R800. In dit artikel wordt alles uitgelegd +over het selecteren van de processor, de DRAM, kloksnelheid +en nog veel meer. In de Sunrise Times vindt u de complete +instructietabellen van de R800, die nog nooit eerder in +Nederland werden gepubliceerd! + + +## T W E E P R O C E S S O R S + +De turbo R bezit twee microprocessors, een Z80 (een Z80A om +precies te zijn) en een R800. Het is dus niet zo dat tijdens +de Z80 mode gewoon de R800 wordt vertraagd, er is +daadwerkelijk een andere processor actief. + +De R800 is upwards compatible met de Z80, en kan dus +alle Z80 instructies verwerken. Maar de R800 kan meer. Ten +eerste kan hij de instructies gemiddeld acht keer sneller +uitvoeren, en ten tweede heeft de R800 een aantal nieuwe +instructies. Om het verschil in snelheid beter te kunnen +uitleggen ga ik u eerst uitleggen wat de term "kloksnelheid" +nu eigenlijk precies betekent. + + +## K L O K S N E L H E I D + +Dit zal u wel een beetje vreemd in de oren klinken, maar de +kloksnelheid zegt eigenlijk weinig over de werkelijke +snelheid van de microprocessor, en nog minder over de totale +snelheid van de computer. + +De Z80A heeft een kloksnelheid van 3.579.545 Hz (meestal +afgekort tot 3.58 MHz). Dit betekent dat de Z80A per seconde +3.579.545 (ruim 3,5 miljoen!) klokpulsen genereert. Tijdens +zo'n klokpuls kan de processor een bepaalde hoeveelheid +taken verrichten. En de truuk is nu, dat deze hoeveelheid +taken per processor niet gelijk is! + +Daarom kan een processor met een lagere kloksnelheid toch +sneller zijn. Een voorbeeld: een R800 die draait op 2 MHz, +is sneller dan een Z80 op 3.58 MHz! Zo ziet u dat de +kloksnelheid slechts weinig zegt. Alleen bij processoren +waarvan alleen de kloksnelheid verschilt, is dat een +duidelijke maatstaf voor de snelheid. Een Z80B die op 7.16 +MHz draait is uiteraard wel twee keer zo snel als een Z80A +die op 3.58 MHz draait, omdat het hier om dezelfde soort +processor gaat. + +Voor de snelheid van de totale computer zegt de kloksnelheid +zoals gezegd nog minder. Daar is namelijk ook de snelheid +van bijvoorbeeld de videochip, en het geheugen van belang. +We kunnen stellen dat een gemiddeld programma op een MSX +turbo R vijf � zes keer sneller is dan op een MSX2. + + +## D E K L O K S N E L H E I D V A N D E R 8 0 0 + +De kloksnelheid van de R800 (dus het aantal klokpulsen van +de R800 per seconde), is 7.159.090 Hz, oftewel precies twee +maal de kloksnelheid van de Z80A. Dit wordt meestal 7.16 MHz +genoemd. Dit betekent overigens dat een klokpuls 1 seconde/ +7159090 = 140 ns (nanoseconde, miljardste seconde) duurt. + +Waarom lees je dan overal (zelfs in de offici�le Japanse +handboeken van Panasonic!) dat de klokfrequentie van de R800 +28.636.360 Hz (28.6 MHz) bedraagt? Dit lijkt onzin, maar is +toch ook weer niet zo heel vreemd. + +Als men zou schrijven dat de R800 een klokfrequentie heeft +van 7.16 MHz (de waarheid!), dan zouden de meeste MSX'ers +waarschijnlijk denken dat deze CPU dus net zo snel is als +een 7.16 MHz Z80. En dat is niet zo, met zuiver rekenwerk is +de R800 gemiddeld (!) acht keer sneller dan een 3.58 MHz +Z80. En zo komt men aan 28.636.360 Hz, dat is namelijk exact +8 maal 3.579.545 Hz! + + +## H O E K A N D A T ? + +Hoe kan het dat de R800 acht maal zo snel is als de Z80, +maar toch maar een twee keer zo hoge kloksnelheid heeft? De +oplettende lezertjes weten het antwoord al: de R800 kan meer +doen in ��n klokpuls dan de Z80! Een voorbeeld: + +De instructie LD A,B neemt op de zowel de Z80 als de R800 1 +zogenaamde "machine cycle" (M-cycle) in beslag. Bij de R800 +duurt een M-cycle ook ��n T-State, maar bij de Z80 duurt die +M-cycle maar liefst vier T-States. + +Het aantal klokpulsen is gelijk aan het aantal T-States plus +eventuele extra klokpulsen. Bij de Z80 is dat er altijd +minimaal 1 (voor de refresh), bij de R800 zijn er een +heleboel instructies waarbij geen extra klokpulsen nodig +zijn (de refresh vindt daar niet bij elke instructie plaats, +maar ongeveer 32 keer per seconde). + +Bij deze instructie (LD A,B) is er bij de Z80 een extra +klokpuls nodig, waardoor het totaal op vijf komt, bij de +R800 is het gewoon ��n klokpuls. Hierdoor is de R800 (bij de +instructie LD A,B) dus vijf keer zo snel als de Z80. + +Bovendien is de klokfrequentie van de R800 twee keer zo hoog +(zoals we al eerder hebben vastgesteld). De instructie wordt +op de R800 dus twee maal vijf is TIEN keer zo snel +uitgevoerd! Even narekenen: een klokpuls duurt bij de R800 +140 ns, en bij de Z80 280 ns. We berekenen nu hoe lang beide +processoren doen over het uitvoeren van de instructie LD +A,B: + +Z80: 5 klokpulsen * 280 ns = 1397 ns +R800: 1 klokpuls * 140 ns = 139,7 ns + +Dit is dus inderdaad precies tien maal zo snel! + +Een overzicht van een aantala andere instructies: + +Instructie: Z80: R800: Versnelling: +------------------------------------------------------------ +LD A,B 5 (1,1) 1 (1,0) 10 +LD A,(HL) 8 (2,1) 3 (2,1) 5,3 +LD A,(IX+0) 21 (5,2) 5 (5,0) 8,4 +PUSH HL 12 (3,1) 4 (4,0) 6 +LDIR (BC<>0) 23 (5,2) 7 (4,3) 6,6 +ADD A,B 5 (1,1) 1 (1,0) 10 +INC A 5 (1,1) 1 (1,0) 10 +ADD HL,DE 12 (3,1) 1 (1,0) 24 (!!!) +INC HL 7 (1,1) 1 (1,0) 14 +JP 11 (3,1) 3 (3,0) 7,3 +JR 13 (3,1) 3 (3,0) 8,7 +DJNZ (B<>0) 14 (3,1) 3 (2,1) 9,3 +CALL 18 (5,1) 6 (5,1) 6 +RET 11 (3,1) 4 (3,1) 5,5 +------------------------------------------------------------ +Gemiddeld 9,36 + +Zoals u ziet is de gemiddelde versnelling in deze tabel dus +9,36 maal, maar u moet niet vergeten dat niet elke +instructie evenveel voorkomt in een routine, dus de +versnelling zal van routine tot routine verschillen. Het is +in ieder geval zeer onwaarschijnlijk dat bovenstaande +instructies (en soortgelijke, want LD D,E duurt natuurlijk +net zo lang als LD A,B) allemaal evenveel voorkomen. De +totale versnelling van een programma is ook nog afhankelijk +van andere zaken, zoals bijvoorbeeld de snelheid van de +videochip (die overigens ongewijzigd is t.o.v. MSX2/2+!). + +Hoe moet u bovenstaande tabel nu lezen? Links staat de +mnemonic, in Z80 formaat. Daarnaast het aantal klokpulsen op +de Z80. De tijd die zo'n instructie vergt kunt u uitrekenen +door dit getal te delen door de kloksnelheid van de Z80. +Daarnaast staan twee getallen tussen haakjes. Het eerste +getal is het aantal M-cycles, het tweede getal het aantal +extra klokpulsen. U kunt het aantal T-states dus vinden door +van het opgegeven aantal klokpulsen dat getal af te trekken. + +De volgende kolom geeft het aantal klokpulsen van dezelfde +instructie op de R800. De tijd kunt u weer uitrekenen door +dit getal te delen door de kloksnelheid van de R800 (wel de +goede nemen natuurlijk). Het eerste getal tussen haakjes is +het aantal M-cycles. Het aantal T-states is bij de R800 +altijd gelijk aan het aantal M-cycles! Het tweede getal +geeft aan hoeveel extra klokpulsen er zijn. Een voorbeeld: + +DJNZ (B<>0) 14 (3,1) 3 (2,1) 9,3 + +Dit moet als volgt worden gelezen: + +Z80: R800: +----------------------------------------------------------- +Klokpulsen: 14 3 +Tijd: 3.91 microseconde 0.42 microseconde +M-cycles: 3 2 +T-states: 13 (14-1) 2 (3-1) +Extra pulsen: 1 1 +Versnelling: 9,3 +------------------------------------------------------------ + +Over het algemeen is het aantal M-cycles op de Z80 en de +R800 gelijk, en komt de versnelling vooral doordat de R800 +maar ��n T-state nodig heeft per M-cycle, en dit er bij de +Z80 meestal 3 � 4 zijn. Bovendien wordt er soms ook nog +"bezuiningd" op de extra klokpulsen. + + +## 1 6 B I T + +De meest opvallende versnelling is toch wel de ADD HL,DE +instruktie, die op de R800 maar liefst 24 keer sneller +wordt. Deze instructie is vooral sneller doordat het aantal +M-cycles drastisch is verminderd van 3 naar 1. Hoe kan dat? +Bij de meeste instructies is het aantal M-cycles bij de R800 +en de Z80 gelijk, zoals eerder opgemerkt. + +Dit komt door de R800 zoveel mogelijk (!) 16 bits is +gemaakt. In Japan wordt er ook geadverteerd dat de R800 16 +bit is. Toch is de R800 niet helemaal 16 bit, de externe +adresbus is namelijk nog steeds acht bits. De hele MSX +computer is acht bits, en als je een processor met een 16 +bits externe adresbus in een MSX zou plaatsen, dan lijkt het +niet veel meer op een MSX! Er zouden dan veel (dure) +aanpassingen nodig zijn. + +Vandaar dat men de externe adresbus ongemoeid heeft gelaten. +Maar intern is de R800 wel 16 bits, en daardoor gaan de 16 +bits instructies (zoals ADD HL,DE) zo ontzettend snel! + + +## D E I N S T R U C T I E T A B E L L E N + +In de Sunrise Times staan de complete instructietabellen van +de R800. Dit is de eerste keer dat deze tabellen in +Nederland worden gepubliceerd!! + +Als u de instructietabellen bekijkt, zult u zien dat de +meeste mnemonics zijn veranderd. De instructies zijn +hetzelfde gebleven, maar de namen zijn gemoderniseerd. Een +overzicht van de instructies die een naamsverandering hebben +ondergaan: + +R800: (nieuwe naam) Z80: (oude naam) +------------------------------------------------------------ +XCH EX +XCHX EXX +MOVE (HL++),(DE++) LDI +MOVE (HL--),(DE--) LDD +MOVEM (HL++),(DE++) LDIR +MOVEM (HL--),(DE--) LDDR +CMP A,(HL++) CPI +CMP A,(HL--) CPD +CMPM A,(HL++) CPIR +CMPM A,(HL--) CPDR +ADDC ADC +SUBC SBC +AND A, AND +OR A, OR +XOR A, XOR +CMP A, CP +CLR RES +ROLA RLCA +RORA RRCA +ROLCA RLA +RORCA RRA +ROL RLC +ROR RRC +ROLC RL +RORC RR +ROL4 (HL) RLD +ROR4 (HL) RRD +SHL SLA +SHR SRL +SHRA SRA +BR JP +BNZ JP NZ, +BZ JP Z, +BNC JP NC, +BC JP C, +BPO JP PO, +BPE JP PE, +BP JP P, +BM JP M, +SHORT BR JR +SHORT BNZ JR NZ, +SHORT BZ JR Z, +SHORT BNC JR NC, +SHORT BC JR C, +DBNZ DJNZ +BRK RST +IN (HL++),(C) INI +IN (HL--),(C) IND +INM (HL++),(C) INIR +INM (HL--),(C) INDR +OUT (C),(HL++) OUTI +OUT (C),(HL--) OUTD +OUTM (C),(HL++) OTIR +OUTM (C),(HL--) OTDR +ADJ A DAA +NOT A CPL +NEG A NEG +NOTC CCF +SETC SCF +------------------------------------------------------------ + +## U I T L E G B I J T A B E L L E N + +Voor degenen die nog nooit een instructietabel hebben gezien +is een beetje uitleg wel op z'n plaats. In de eerste kolom +staat de mnemonic, de "syntax" van de instructie. Daarnaast +een symbolische notatie van de werking van deze instruktie. +In de volgende kolom wordt aangegeven hoe de vlaggen worden +be�nvloedt. Daarvoor worden de volgende tekens gebruikt: + +stip vlag wordt niet be�nvloedt +pijltje stand van vlag wordt bepaald door de uitkomst van +de instructie +0 vlag staat op 0 na instructie +1 vlag staat op 1 na instructie +? vlag onbekend +P P/V vlag geeft pariteit +V P/V vlag geeft overflow + +In de volgende kolommen wordt de opcode gegeven, in binair +en in hexadecimaal. De kolom "B" geeft aan hoeveel bytes de +instructie in beslag neemt, de kolom "C" het aantal M-cycles +(C is dus een afkorting van Cycles). Zoals we eerder hebben +vastgesteld is dit altijd gelijk aan het aantal T-states, +maar het aantal klokpulsen kan een paar meer zijn. + +Verder worden nog een heleboel symbolen gebruikt. Een +overzicht: + +a{7} bit 7 van register a +a{4..7} bit 4 t/m 7 van register a +de:hl een 32 bits waarde, waarbij DE de hoogste +16 bits bevat +(ix+d) d is de 8 bits offset +C carry vlag +Z zero vlag +P/V parity/overflow vlag +S sign vlag +N subtract vlag +H half-carry vlag +IFF interrupt flipflop +r,r' A,B,C,D,E,H,L +u,u' A,B,C,D,E,IXH,IXL +v,v' A,B,C,D,E,IYH,IYL +p IXH,IYL +q IYH,IYL +ss BC,DE,HL,SP +pp BC,DE,IX,SP +rr BC,DE,IY,SP +qq BC,DE,HL,AF +e offset bij SHORT BR (JR bij Z80) +k adres bij BRK (RST bij Z80) +nn 16 bits constante +n 8 bits constante +b bitnummer (0-7) +NOT logische bewerking +tmp tijdelijke opslag van een bit +B aantal bytes +C aantal (M) cycles + +Voor de logische bewerkingen OR, XOR en AND worden de +wiskundige notaties gebruikt (OR is een "V", XOR een +"omgekeerde A" en AND een "omgekeerde V"). + + +## O P C O D E S S A M E N S T E L L E N + +De instructietabellen zouden wel erg lang worden als per +mogelijke instructie de opcode zou zijn vermeld. Bovendien +is dan de logica in de opcodes niet meer uit de tabel op te +maken. Vaak moet de opcode dan ook (op binaire wijze) zelf +worden samengesteld. Met een voorbeeld kan ik het beste +laten zien hoe dat gaat. + +U wilt bijvoorbeeld de opcode van de instructie LD C,H +weten. Als u de instructietabellen in de Sunrise Times erbij +pakt, kunt u daar LD r,r' vinden. In de kolom opcode staat: + +7 6 5 4 3 2 1 0 <-- bitnummers +0 1 r r' <-- opcode + +Onderaan ziet u de tabel voor r en r'. U ziet daar dat 001 +staat voor C en 100 voor H. U vervang nu r en r' in de +binaire opcode door de gevonden codes voor C en H. De opcode +wordt dan: + +7 6 5 4 3 2 1 0 <-- bitnummers +0 1 0 0 1 1 0 0 <-- opcode + +U heeft de opcode gevonden, het is &B01001100. + + +## N I E U W E I N S T R U C T I E S + +De R800 kent ten opzichte van de Z80 drie geheel nieuwe +instructies, bovendien zijn de indexregisters (IX en IY) nu +ook per 8 bits aanspreekbaar. U kunt in de +instructietabellen opzoeken bij welke instructies dat +mogelijk is, te herkennen aan u, v, p of q. + +De andere nieuwe instructies zijn: +``` +IN F,(C) +MULUB A,r +MULUW HL,ss +``` +De eerste instructie is erg handig. Routines waarbij (een) +bepaald(e) bit(s) in de gaten wordt gehouden, worden door +deze instructies korter, sneller en gebruiken minder +registers. Een voorbeeld: stel u moet bit 0 van I/O poort C +in de gaten houden. De routine moet net zolang wachten tot +bit 0 op 0 staat. Op de Z80 zou dat er als volgt uit zien: +``` +WACHT: IN A,(C) +BIT 0,A +JR NZ,WACHT +``` +Dit zijn 6 bytes en het A-register wordt gebruikt. + +Op de R800 kan het ook zo: +``` +WACHT: IN F,(C) +JR C,WACHT +``` +Dit zijn 4 bytes en het A-register wordt niet gebruikt. +Bovendien is deze manier sneller. (N.B. Het carry bit is bit +0 van het F-register.) + + +## V E R M E N I G V U L D I G E N ! + +Echt super zijn de vermenigvuldigingsinstructies van de +R800. De instructie MULUB (MULtiply Bytes) vermenigvuldigt A +met B, C, D of E en zet het 16 bits antwoord in HL. Dit gaat +razendsnel, deze instructie gebruikt slechts 14 klokpulsen +(1.96 micro- seconde). + +De instructie MULUW (MULtiply Words) vermenigvuldigt HL met +BC of SP (zal in de praktijk meestal BC zijn), en zet het +antwoord in DE en HL, waarbij de hoogste bits in DE terecht +komen. Deze instructie duurt slechts 5.03 microseconde (36 +klokpulsen)! + +Deze twee instructies zijn ontzettend krachtig en maken zeer +snelle "realtime calculated" animaties mogelijk, +bijvoorbeeld vectorgraphics. Ook voor fractals is dit erg +handig, die kunnen nu veel en veel sneller worden berekend. + +Een leuke vergelijking met de Z80 is dat de MULUW HL,BC +instructie op de R800 net zolang duurt als een CALL +instructie op de Z80!! Bij de Z80 moet voor vermenigvuldigen +een aparte routine worden geschreven, en als je die met een +CALL aanroept is de R800 in de tussentijd al klaar met de +complete vermenigvuldiging. U begrijpt wel dat de R800 als +het om vermenigvuldigen gaat veel meer dan acht maal sneller +is, ik denk wel honderd maal sneller. Bovendien spaart het +een hoop programmeertijd, want berekeningen kunnen een stuk +makkelijker worden geprogrammeerd. + +Onderstaand voorbeeld is een routine die HL=A*B uitrekent. +Op de R800 is ��n instructie daarvoor voldoende: MULUB A,B. +Deze instructie is sneller dan een CALL instructie bij de +Z80! Bij de Z80 zou je dan ongeveer zo'n routine krijgen: +``` +; MULUB A,B voor de Z80 +; Door Stefan Boer +; Voor Sunrise Special #1 +; Werking: HL=A*B +; In: A,B +; Uit: HL +; Gebruikt: DE +; Methode: Herhaald optellen + +MULUB: LD HL,0 +LD E,A +LD D,0 ; LD DE,A +XOR A +CP B +RET Z ; B=0, dan antwoord 0 +MULTI: ADD HL,DE +DJNZ MULTI ; tel B maal DE bij HL op +RET +``` +U kunt zien dat dit heel wat meer bytes en tijd in beslag +neemt, de CALL MULUB duurt op de Z80 al langer dan de MULUB +A,B instructie op de R800. + + +## R 8 0 0 A S S E M B L E R ? + +Nu denkt u misschien dat u een nieuwe assembler nodig heeft +als u software voor de R800 wilt ontwikkelen. Dit is zeker +niet het geval! Alle bestaande Z80 assemblers kunnen gewoon +worden gebruikt. Dit is ook de reden waarom er nog geen +speciale R800 assembler op de markt is gebracht. + +Het zou trouwens ook verwarrend zijn voor een programmeur +die de Z80 assemblertaal al beheerst, om de nieuwe mnemonics +voor de R800 te leren. + +"En de nieuwe instructies dan?" hoor ik u denken. Nu, die +kunt u gewoon met DEFB instructies simuleren! Alleen de +disassembler zal hier een beetje van in de war raken, maar +dat is toch niet zo'n ramp? Ik zal nu voor alle nieuwe +instructies uitleggen hoe ze met een gewone Z80 assembler +(zoals WB-ASS2) kunnen worden gebruikt. + + +## I N D E X R E G I S T E R S + +Bij de indexregisters IX en IY is het ontzettend makkelijk. +Het is u vast al wel eens opgevallen, dat de opcodes +hetzelfde zijn als die voor de instructies voor HL, behalve +dan dat er een extra code voor staat. Die code is &HDD voor +IX en &HFD voor IY. Een voorbeeld: + +Mnemonic: Opcode: + +LD HL,&H1BBF 21 BF 1B +LD IX,&H1BBF DD 21 BF 1B +LD IY,&H1BBF FD 21 BF 1B + +U kunt voor alle instructies met IXL, IXH, IYL en IYH de +assembler op een heel eenvoudige manier voor de gek houden. +Voor IXL en IYL zet u een L en voor IYH en IXH een H. Door +er een DEFB &HDD voor te zetten wordt de L resp. H voor de +R800 IXL resp. IXH, met een &HFD hetzelfde voor IY. +Voorbeelden: +``` +DEFB &HDD +LD A,L ; LD A,IXL + +DEFB &HFD +LD L,H ; LD IYL,IYH + +DEFB &HDD +LD H,B ; LD IXH,B +``` +Zoals u ziet is de instructie LD IXH,IYL niet mogelijk, u +kunt immers niet de code voor IX �n de code voor IY voor een +instructie plaatsen. Maar verder is alles mogelijk, zie de +instructietabellen in de Sunrise Times. + + +## I N F , ( C ) + +Voor deze instructie kunt u gewoon DEFB &HED,&H70 invullen. +U kunt dat het beste zo in de assemblerlisting zetten: +``` +DEFB &HED,&H70 ; IN F,(C) +``` +Zo kunt u goed zien dat het geen data bytes zijn maar +eigenlijk gewoon een opcode. Door een foutje in die +assemblers zullen sommige assemblers dit overigens +disassembleren als IN (HL),(C). Dit is een niet bestaande +instructie, maar het komt omdat IN F,(C) voor de R800 gewoon +een speciaal geval is van IN r,(C). Bij andere instructies +(bijvoorbeeld LD A,(HL)) wordt (HL) weergegeven door +dezelfde bits als F bij de IN F,(C) instructie, vandaar de +fout. + + +## M U L U B E N M U L U W + +Voor deze instructies kunt u de instructietabellen van de +R800 die in de Sunrise Times staan afgedrukt gebruiken. U +kunt de opcodes aan de hand daarvan samenstellen (zie het +stukje over opcodes samenstellen), en ze met DEFB +instructies in de code opnemen. Bijvoorbeeld: + +DEFB &HED,&B11000001 ; MULUB A,B + +Ook hier is het weer aan te raden om bij het commentaar de +R800 mnemonic in te vullen, zo houdt u uw assemblerlistings +leesbaar. + +## S C H A K E L E N + +Nu zit ik wel een lang artikel over de R800 te schrijven, +maar als u niet weet hoe u deze wonderprocessor moet +selecteren heeft u daar nog niet veel aan. + +In het MAIN ROM van de MSX turbo R zitten vier nieuwe BIOS +routines, waarvan er twee voor het schakelen tussen de Z80 +en de R800 zijn bedoeld. Dat zijn: +``` +CHGCPU &H0180 Selecteer CPU +Invoer: A register +MSB 7 6 5 4 3 2 1 0 LSB +LED 0 0 0 0 0 X X +LED=1: led wordt bestuurd +LED=0: led wordt niet bestuurd +XX=00: Z80 +XX=01: R800 ROM +XX=10: R800 DRAM +Gebruikt: AF + +GETCPU &H0183 Bepaal huidige CPU +Invoer: - +Uitvoer: A register +0: Z80 +1: R800 ROM +2: R800 DRAM +``` + +Over LED is wegens foutieve publikaties in andere +Nederlandse MSX bladen een misverstand ontstaan. Dit bit +bestuurt niet het led (1=aan, 0=uit), maar bepaalt of de +status van het led (aan of uit) door de gekozen CPU moet +worden be�nvloed! + +Stel u zit in R800 mode en het lampje brandt. Doet u nu LD +A,0 en daarna CALL CHGCPU, dan zal de Z80 uitgaan, maar het +lampje blijft branden. Bit 7 van register A (LED) is immers +0, en dus zal het led niet door de gekozen CPU (Z80, normaal +gesproken moet het lampje dus uit!) worden be�nvloed. + +Andersom kan ook, als u in Z80 mode zit (lampje uit) en u +selecteert de R800 mode door een CALL &H180 te geven terwijl +het A register de waarde 1 bevat (R800), dan zal de R800 wel +aangaan, maar het lampje niet! + +Bij "normaal" gebruik van deze BIOS routine, waarbij de +stand van het lampje in overeenkomst is met de actieve +processor (aan=R800, uit=Z80), dient u dus ��n van de +volgende drie waardes te gebruiken: + +&H80 Z80 +&H81 R800 ROM +&H82 R800 DRAM + +U kunt met GETCPU opvragen welke processor er op dat +ogenblik actief is. U kunt op de volgende manier dus het +lampje in de goede stand zetten: +``` +CALL &H183 ; welke CPU actief? +SET 7,A ; LED besturen aan +CALL &H180 ; CPU zelfde, LED besturen +``` + +## D R A M + +Ik heb het in bovenstaande tekst vrolijk over DRAM, zonder +uit te leggen wat dat nou eigenlijk inhoudt. De DRAM mode is +een slimme truuk, die ook door andere moderne computers +wordt gebruikt. In feite is het niet de R800 die voor de +DRAM mode zorgt, maar de S1990. + +Bij de Z80 maakt het niet uit of er RAM of ROM wordt +gelezen, dit gaat beiden even snel. Omdat er in de turbo R +dezelfde ROMs worden gebruikt als in een MSX1/2/2+, moeten +die op een langzame snelheid worden gelezen. Telkens als de +R800 ROM moet lezen, schakelt hij even terug naar een +langzamere snelheid. Vandaar dat op een R800 het lezen van +RAM sneller is dan ROM, want in de turbo R wordt "snel" RAM +gebruikt, zodat terugschakelen niet nodig is. + +Vooral in BASIC wordt er continu uit de ROM gelezen. De +BASIC zelf staat immers op ROM! De R800 ROM mode is daarom +in BASIC helemaal niet zo snel, omdat er telkens wordt +teruggeschakeld naar een lagere snelheid. De oplossing is de +DRAM mode. + + +## R O M I N R A M + +Bij het opstarten van de computer wordt de 64 kB meest +gebruikte ROM naar de bovenste 64 kB van het RAM gekopieerd. +De turbo R heeft dan dus 64 kB minder werkgeheugen over. De +ROM die gekopieerd wordt is: + +MAXPGE-3: MAIN ROM 0000-3FFF +MAXPGE-2: MAIN ROM 4000-7FFF +MAXPGE-1: SUB ROM +MAXPGE : KANJI ROM + +Voor MAXPGE moet u het hoogste memorymapper segment +invullen. De FS-A1ST heeft bijvoorbeeld 256 kB, dat zijn 16 +memorymapper segmenten van 16 kB. Daar het nummeren bij 0 +begint, is MAXPGE dus gelijk aan 15. De SUB ROM staat dus in +memorymapper segment 14. + +Als de DRAM mode wordt geselecteerd komt de S1990 in actie. +Wordt nu ��n van de hierboven genoemde ROMs gelezen door de +R800, dan zorgt de S1990 ervoor dat niet de ROM maar de RAM +(waarin het ROM is gekopieerd) wordt gelezen. De R800 hoeft +dan niet te wachten op het langzame ROM, en werkt een stuk +sneller. De S1990 zorgt ervoor dat er niet in de DRAM kan +worden geschreven (zo heet de tot ROM verklaarde RAM), en +zorgt er tevens voor dat het RAM dat voor de DRAM wordt +gebruikt niet meer te gebruiken is. Probeert u er toch iets +uit te lezen, dan zal dat altijd de waarde &HFF opleveren. + + +## R O M M O D E E N D R A M M O D E + +Er zijn dus twee verschillende R800 standen. Bij de R800 ROM +mode gaat het net als bij de Z80 mode, er wordt gewoon ROM +gelezen. Vandaar de naam ROM mode. Deze mode is vooral onder +BASIC langzaam, omdat daar veel ROM wordt gelezen. Onder +machinetaal springt de computer ook 60 keer per seconde naar +ROM, voor de interrupt routine op &H38. Ook als het +machinetaalprogramma de BIOS gebruikt zal er naar het ROM +worden gesprongen. Daarom heeft het selecteren van de DRAM +mode ook bij machinetaal zin, al is heeft het minder effect +dan bij BASIC. De R800 ROM mode heeft als belangrijkste +voordeel dat het volledige RAM geheugen vrij is als +werkgeheugen. + +De DRAM mode is sneller, maar kost wel 64 kB geheugen. U +kunt dus zelf per situatie beslissen of u de ROM mode of de +DRAM mode wilt gebruiken. + + +## I N R O M P O K E N ! + +U kunt bij de turbo R als het ware in het ROM POKEn. Dit +gaat als volgt: + +- Selecteer de R800 ROM mode (of Z80 mode) + +In de bovenste 64 kB van de memorymapper staat nu een kopie +van de ROM, waar u net zoveel in kunt knoeien als u wilt. +Als u klaar bent + +- Selecteert u de R800 DRAM mode + +Nu wordt het RAM waar u zojuist in hebt geknoeid gebruikt +voor de DRAM, en dus hebt u als het ware in de ROM gePOKEt! + + +## P A S O P ! + +Je zou misschien denken dat het ROM elke keer dat de DRAM +wordt geselecteerd in het RAM wordt gekopieerd. Dat is niet +zo, anders zou bovenstaande truuk ook niet werken. De reden +hiervoor is dat het kopi�ren van 64 kB toch wel even tijd +kost, en op die manier zou de CHGCPU routine veel te +langzaam worden. + +Het ROM wordt alleen bij een reset in het RAM gekopieerd, en +hiermee dient terdege rekening gehouden te worden! Als u de +DRAM mode selecteert terwijl het RAM dat voor de DRAM mode +wordt gebruikt verminkt is, kan dit onverwachte gevolgen +hebben! + + +## D I S K G E B R U I K E N R 8 0 0 + +Het aansturen van de diskdrive gaat niet goed onder R800 +stand. De diskcontroller kan bij zo'n hoge snelheid de +processor blijkbaar niet bijhouden. Tenminste, bij het +saven. Het laden onder R800 stand gaat prima, maar bij saven +kan er van alles mis gaan. Het gaat niet altijd fout, maar +vaak treedt er een Disk I/O error op of er wordt gewoon +niets gesaved. + +Bij MSX-DOS2.31/MSX Disk BASIC 2.01 is daar rekening mee +gehouden. Bij elke diskactie wordt de R800 stiekem uitgezet. +Ik schrijf "stiekem", omdat het lampje niet wordt uitgezet. +Dat blijft branden, omdat de R800 wordt uitgezet door +``` +LD A,0 +CALL &H180 ; R800 uit, lampje niet +``` +En u hebt aan het begin van het artikel al geleerd dat het +lampje dan niet uitgaat. Hierdoor wordt behalve het saven +ook het laden vertraagd, wat eigenlijk niet nodig is. + +De ontwikkelaars van de turbo R hebben dit in de MSX- +DOS2.31/Disk BASIC 2.01 ROMs ingebouwd, omdat dat normaal +gesproken onder R800 stand wordt gedraaid. + + +## D O S 1 M O D E + +Onder DOS1 mode (MSX-DOS1.11/Disk BASIC 1.0) wordt dit niet +gedaan. Die stand is tenslotte bedoeld voor het uitvoeren +van MSX1/2/2+ programma's, en die werken toch onder Z80 +stand. + +Toch zullen programmeurs vaak MSX turbo R software voor DOS1 +mode ontwikkelen, omdat de geheugenhuishouding van DOS2 +nogal irritant is. De R800 wordt dan dus aangezet onder DOS1 +mode, terwijl de diskROM daar geen rekening mee houdt. + +In het technical databook van de turbo R staat dan ook dat +als een programmeur toch de combinatie DOS1/R800 gebruikt, +hij bij elke diskactie de R800 uit moet zetten. De +programmeur van Seed of Dragon heeft zich daar netjes aan +gehouden; elke keer als het disklampje gaat branden zie je +bij dat spel het R800 lampje uitgaan. + +Hoewel dit niet in het technical databook staat, kan de R800 +bij het laden rustig aan blijven staan. Alleen bij saven +zijn er problemen. Onder R800 stand gaat het laden zelfs +aanmerkelijk sneller! MicroCabin wist dit blijkbaar ook, +want bij bijvoorbeeld Fray wordt de R800 alleen uitgezet als +er wordt gesaved. + +Conclusie: + +Z E T D E R 8 0 0 A L T I J D U I T A L S + +E R I N D O S 1 M O D E N A A R D I S K + +W O R D T G E S C H R E V E N ! ! ! + + +Nogmaals: bij laden kunt u de R800 rustig aan laten staan. + + +## P A G E M O D E A C C E S S + +Bij het bekijken van een artikel over de R800 in een Japans +blad kwam ik de term "DRAM page access" tegen, en ik had +eerst geen flauw idee wat dat was. Later kwam ik er wel +achter. + +Wanneer van het adres in de externe databus de high-byte +niet verandert, zal de R800 de high-byte van het adres niet +opnieuw op de adresbus plaatsen (lijkt heel logisch, maar de +Z80 kent deze truuk niet!) + +Een "page" is in de processorwereld een stukje geheugen van +256 bytes, dat op een 256-byte grens begint, dus &H??00 - +&H??FF. Verwar dit niet met de bij MSX bekende term "page", +een stuk geheugen van 16 kB. + +Het hierboven beschreven truukje dat de R800 gebruikt heet +"Page mode access" en verhoogt de snelheid nog eens met +ongeveer een factor twee. + +De programmeur kan met "paged DRAM access" maximaal van deze +truuk gebruik maken. Paged DRAM access betekent dat alle +geheugentoegang van een routine (dus ook de routine zelf) in +dezelfde page staat (bijvoorbeeld &HD000-&HD0FF). Dit is wel +zeer beperkt, want met alle geheugentoegang bedoel ik dan +dus echt ALLE geheugentoegang, inclusief stack, variabelen +en constanten. Het uitzetten van de interrupts is in verband +met die stack dan ook ten zeerste aan te raden. Maar deze +moeite wordt wel beloond met een ultra-snelle routine! + +We begrijpen nu ook beter hoe het komt dat een LD A,B +instruktie op de R800 tien keer zo snel is dan op de Z80, +terwijl een LD A,(HL) maar 5,3 keer zo snel is. + +Bij het uitvoeren van een instructie hoort namelijk ook het +ophalen van de opcode uit het geheugen. Omdat bij een LD A,B +instructie de externe adresbus niet wordt gewijzigd, hoeft +bij het ophalen van de volgende opcode (meestal) alleen de +low-byte van de externe adresbus te worden veranderd. Bij de +LD A,(HL) instructie is de externe adresbus wel veranderd, +zodat zowel de low- als de high-byte van het PC register +(Program Counter) naar de externe adresbus moeten worden +verplaatst. + + +## T O T S L O T + +Tot slot wil ik Alex Wulms nog bedanken voor zijn +medewerking, een gedeelte van de informatie in dit artikel +is van hem afkomstig. De overige informatie heb ik zelf +uitgevonden of komt uit Japanse bladen. + +De R800 is (inclusief toetsenbord, diskdrive, kast en een +zooitje chips onder de naam FS-A1GT) te koop bij MSX Club +Gouda voor fl. 1795,-. Verplicht voor elke MSX'er die bij de +tijd wil blijven (maar nu nog een antieke MSX2 heeft)! + +Stefan Boer \ No newline at end of file diff --git a/sunrise_special/2/Blinkmode.md b/sunrise_special/2/Blinkmode.md new file mode 100644 index 0000000..f3c9a38 --- /dev/null +++ b/sunrise_special/2/Blinkmode.md @@ -0,0 +1,797 @@ +# B L I N K M O D E + + +Ik ga ervan uit dat de blinkmode in Text Mode 2 (SCREEN 0 +WIDTH 80) bij de lezer bekend is. Voor elke positie op het +scherm is er een bit in de blinktabel die aangeeft of de +positie "blinkt" of normaal is. + +Door deze binaire opbouw is het aansturen van de blink mode +behoorlijk gecompliceerd. Ik heb daarom een standaard ML +routine geschreven waarmee van een bepaalde rechthoek de +blinkmode aan of uit kan worden gezet. + + +## G E B R U I K I N B A S I C + +Ik heb de routine meteen maar in een CMD jasje gestoken, +zodat hij vanuit BASIC te gebruiken is. Dit heeft extra +voordelen, de routine bespaart nu niet alleen een hoop +rekenwerk, maar ook veel tijd. + +Met een BLOAD"CMDBLINK.BIN",R initialiseert u vier +nieuwe BASIC commando's: +``` +CMD BFIL (x1,y1)-(x2,y2) +CMD BRES (x1,y1)-(x2,y2) +CMD BCOL (voorgrondkleur,achtergrondkleur) +CMD BTIM (normaaltijd,blinktijd) +``` + +Met (x1,y1)-(x2,y2) geeft u een rechthoek op, net als bij +LINE(x1,y1)-(x2,y2),,BF. De x co�rdinaten moeten liggen +tussen 0 en 79, de y co�rdinaten tussen 0 en 26 (de onderste +2.5 regel wordt alleen getoond als bit 7 van R#9 gelijk is +aan 1). Met CMD BFIL zet u de blinkmode aan in die rechthoek +en met CMD BRES zet u de blinkmode uit. + +De voorgrondkleur en achtergrondkleur moeten natuurlijk +tussen 0 en 15 liggen, ook de normaaltijd en de blinktijd +moeten tussen 0 en 15 liggen. De tijd wordt opgegeven in +eenheden van ca. 1/6 seconde. + + +## C M D + +Voordat we met de assemblerlisting gaan beginnen moet ik +natuurlijk eerst nog even uitleggen hoe CMD werkt. CMD is +een afkorting van CoMmanD, en is speciaal bedoeld voor +toekomstige uitbreidingen van BASIC. In feite is er alleen +een hook voor gereserveerd op adres &HFE0D, zodra de BASIC +interpreter het commando CMD tegenkomt wordt er naar deze +hook gesprongen. + +Normaal gesproken staat hier een RET, en zal er een +foutmelding worden gegeven. Wordt de CMD hook echter +afgebogen, dan kan er een eigen commando aan worden +gehangen. Eventueel kunnen er meerdere CMD commando's worden +gecre�erd door te kijken naar de karakters die na het CMD +commando staan. Dit wordt hier ook gedaan. + +Als u met een gewone RET terugspringt zal er een foutmelding +volgen, zo hebben we net gezien. We moeten er dus voor +zorgen dat het terugspringadres van de stack wordt gehaald, +dit doen me met een extra POP AF. + +HL wijst naar de plaats in het BASIC programma, in het geval +van aanroep van de CMD hook dus naar het adres direct achter +CMD in het BASIC programma. Hier kunnen eventueel parameters +worden doorgegeven, wat bij deze routine dan ook gebeurt. +Bij het terugspringen naar BASIC moet HL wijzen naar de +positie direct achter het complete CMD commando. + +Nu is het tijd voor de assemblerlisting. Zoals gewoonlijk +zal ik hem regelmatig onderbreken voor commentaar. De +listing is aanwezig op de disk onder de naam "CMDBLINK.ASC". + +``` +; C M D B L I N K . A S M +; Gebruikt BLINK +; Door Stefan Boer 21/10/92 +; Sunrise Special #2 - (c) Stichting Sunrise 1992 + +; Maakt nieuwe BASIC commando's voor blink mode +; (SCREEN 0 WIDTH 80) +; BFIL, BRES, BCOL en BTIM + +; Syntax: CMD BFIL (X1,Y1)-(X2,Y2) +; CMD BRES (X1,Y1)-(X2,Y2) +; Zet blinkmode aan (BFIL) of uit (BRES) in een bepaalde +; rechthoek +; 0 <= X1,X2 <=79 +; 0 <= Y1,Y2 <=26 + +; Syntax: CMD BCOL (V,A) +; Stel blinkkleuren in +; 0 <= V,A <= 15 +; V=voorgrondkleur, A=achtergrondkleur + +; Syntax: CMD BTIM (N,B) +; Stel blinktijden in +; 0 <= N,B <= 15 +; N=tijd normale kleuren, B=tijd blinkkleuren +; tijd in eenheden van ca. 1/6 seconde + +H_CMD: EQU &HFE0D ; hook +GETBYT: EQU &H521C ; BASIC haal byte -> E en A +SYNTAX: EQU &H4055 ; Syntax error + + ORG &HD000 + +; buig de hook af + +INIT: LD HL,HOOK + LD DE,H_CMD + LD BC,5 + LDIR + RET + +; de nieuwe hook + +HOOK: POP AF ; wis terugspringadres + CALL PROG + RET +``` + +Met een CALL INIT wordt de nieuwe hook over de oude CMD hook +gezet. De POP AF zorgt ervoor dat er geen foutmelding zal +volgen na het uitvoeren van een van de nieuwe BASIC +commando's. De nieuwe hook roept daarna PROG aan. + +``` +; dit wordt aangeroepen bij een CMD + +PROG: RST 8 + DB "B" ; eerste letter altijd "B" +``` + +HL wijst naar de huidige positie in het BASIC programma. Bij +aanroep van PROG is dit dus de positie direct achter de code +voor CMD. Hierachter moet een "B" staan, omdat al onze +nieuwe commando's met een B beginnen. + +Met de BIOS routine SYNCHR (adres &H0008, aanroep RST 8) is +het zeer eenvoudig om te controleren of een bepaalde code +(hier dus "B") op de huidige positie (die wordt gegeven door +HL) in het BASIC programma staat. Na de RST 8 geef je met +een DB de code op. Wordt deze code gevonden, dan springt de +computer naar CHRGTR (adres &H0010, aanroep RST &H10) en +haalt de code op, dit is voor ons hier verder niet +belanrijk. Wordt de code echter niet gevonden, dan volgt er +een foutmelding. HL wordt automatisch verzet naar de +volgende positie, waarbij spaties automatisch worden +overgeslagen. + +``` + LD A,(HL) + INC HL + CP "F" ; bFil + JP Z,BFIL + CP "R" ; bRes + JP Z,BRES + CP "C" ; bCol + JP Z,BCOL + CP "T" ; bTim + JP Z,BTIM + JP SYNTAX ; Syntax error +``` + +Hier wordt de volgende code opgehaald, HL wordt daarna op de +volgende positie gezet met een INC HL. Vervolgens wordt naar +de letter direct achter de B gekeken om te kijken welk +commando het is. Dit wordt met CP's en voorwaardelijke JP's +gedaan. Wordt geen van de tweede letters gevonden, dan staat +er blijkbaar een verkeerd woord achter CMD en wordt een +foutmelding gegeven. + +``` +BFIL: RST 8 + DB "I" + RST 8 + DB "L" ; bfIL + LD A,1 ; blink aan + LD (MODE),A + JP FILRES +``` + +Hier wordt naartoe gesprongen als er "BF" is gevonden. Eerst +moet er dus nog worden gecontroleerd of er ook inderdaad +BFIL stond, door met RST 8 te controleren of er "IL" volgt. +Zo nee, dan zorgt RST 8 zelf voor de foutmelding. Zo ja, dan +wordt (MODE) op 1 gezet. Met (MODE) wordt bepaald of in de +rechthoek de blinkmode aan- of uitgezet wordt. Vervolgens +wordt er naar FILRES gesprongen, vanaf daar is de routine +voor BFIL en BRES hetzelfde. + +``` +BRES: RST 8 + DB "E" + RST 8 + DB "S" ; brES + XOR A ; blink uit + LD (MODE),A +``` + +Dit is ongeveer hetzelfde, alleen nu voor BRES. (MODE) wordt +nu op 0 gezet, een JP FILRES is niet nodig omdat FILRES hier +direct achter staat. + +``` +; routine voor BFIL en BRES (MODE is al ingevuld) + +FILRES: RST 8 + DB "(" + CALL GETBYT ; lees X1 + LD (BEGIN+1),A + RST 8 + DB "," +``` + +Eerst wordt op het haakje openen gecontroleerd, vervolgens +wordt met de routine GETBYT van de BASIC interpreter de +eerste x co�rdinaat opgehaald. GETBYT verhoogt zelf HL en +zet het resultaat in A en in E. We bewaren de eerste x +co�rdinaat en controleren vervolgens op de komma. + +``` + CALL GETBYT ; lees Y1 + LD (BEGIN),A + RST 8 + DB ")" + RST 8 + DB &HF2 ; is "-" +``` +Hier wordt de eerste y co�rdinaat opgehaald. Vervolgens +wordt het haakje sluiten gecontroleerd en het streepje. Let +op: dit kan niet met RST 8, DB "-", omdat het token voor het +streepje niet gelijk is aan de ASCII code, maar &HF2! + +``` + RST 8 + DB "(" + CALL GETBYT ; lees x2 + LD (EIND+1),A + RST 8 + DB "," + CALL GETBYT ; lees y2 + LD (EIND),A + RST 8 + DB ")" + PUSH HL ; save BASIC pointer +``` + +Hier worden ook de tweede x- en y co�rdinaten opgehaald. +Vervolgens wordt HL bewaard, want die moet bij het +terugkeren naar BASIC wijzen naar de positie direct achter +het commando. + +``` + LD BC,(BEGIN) ; aanroep standaardroutine + LD DE,(EIND) ; met juiste waarden + LD A,(MODE) ; in registers + CALL BLINK ; (B,C)-(D,E), A=aan/uit +``` + +Hier worden de registers met de juiste waardes gevuld voor +de standaardroutine BLINK. De routine wordt vervolgens +aangeroepen. De standaardroutine BLINK staat aan het einde +van de assemblerlisting. + +``` + POP HL ; BASIC pointer terug + RET ; terug naar BASIC +``` + +Het commando is uitgevoerd, dus we gaan terug naar BASIC. +Eerst wordt natuurlijk de juiste waarde van HL weer +teruggehaald. Nu de routines voor BCOL en BTIM. + +``` +BCOL: RST 8 + DB "O" + RST 8 + DB "L" ; bcOL + RST 8 +``` +Eerst controleren we wel of er echt BCOL stond. +``` + DB "(" + CALL GETBYT ; lees voorgrondkleur + AND &H0F + ADD A,A + ADD A,A + ADD A,A + ADD A,A + LD (BUF1),A +``` +Vervolgens controleren we op het haakje en halen we de +voorgrondkleur op. Deze verplaatsen we naar de 4 hoogste +bits, en we slaan deze waarde zolang op in (BUF1). + +``` + RST 8 + DB "," + CALL GETBYT ; lees achtergrondkleur + AND &H0F + LD (BUF2),A + RST 8 + DB ")" +``` + +Ook de achtergrondkleur wordt opgehaald. De AND instructie +is nodig omdat alleen de onderste vier bits van belang zijn. +Deze waarde wordt in (BUF2) opgeslagen, en er wordt +gecontroleerd of het laatste haakje er wel staat. + +``` + LD A,(BUF1) + LD C,A + LD A,(BUF2) + OR C + LD (&HFFEB),A ; voor compatibiliteit BASIC + DI + OUT (&H99),A + LD A,12+128 ; blinkkleuren naar R#12 + OUT (&H99),A + EI + RET +``` + +De juiste waarde wordt berekend en naar VDP register 12 +gestuurd, dit is hetzelfde als VDP(13). Om te zorgen dat in +BASIC de waarde van VDP(13) nog kan worden opgevraagd zetten +we de waarde ook op de juiste plaats in het systeem RAM. HL +wordt hier niet veranderd, daarom hoeft hij niet te worden +gePUSHd en gePOPt. + +``` +BTIM: RST 8 + DB "I" + RST 8 + DB "M" ; btIM + RST 8 + DB "(" + CALL GETBYT ; lees normaaltijd + AND &H0F + LD (BUF1),A + RST 8 + DB "," + CALL GETBYT ; lees blinktijd + AND &H0F + ADD A,A + ADD A,A + ADD A,A + ADD A,A + LD (BUF2),A + RST 8 + DB ")" + LD A,(BUF1) + LD C,A + LD A,(BUF2) + OR C + LD (&HFFEC),A ; voor compatibiliteit BASIC + DI + OUT (&H99),A + LD A,13+128 ; blinktijden naar R#13 + OUT (&H99),A + EI + RET + +BUF1: DS 1 +BUF2: DS 1 +``` + +De routine voor BTIM lijkt zo sterk op de routine voor BCOL +dat ik hier verder niets aan heb toe te voegen. Dit +gedeelte van de routine is nu klaar, alleen de standaard +blink routine moet nog worden toegevoegd. + +``` +; BLINK +; Standaardroutine voor blinkmode SCREEN0:WIDTH80 (T2) +; Door Stefan Boer 21/10/92 +; Sunrise Special #2 - (c) Stichting Sunrise 1992 + +; Invoer: (B,C)-(D,E) rechthoek +; A=0: wissen / A<>0: zetten + +LDIRVM: EQU &H5C +LDIRMV: EQU &H59 + +; check of B<=D en C<=E, verwissel indien nodig + +BLINK: LD (MODE),A ; bewaar mode + LD A,D + CP B + JR NC,CHECK2 + LD L,D + LD D,B + LD B,L ; verwissel B en D +``` + +Voor het juist functioneren van de BLINK routine moet B +kleiner of gelijk zijn aan D en C kleiner of gelijk zijn aan +E. Dit wordt gecontroleerd, de waardes van de registers +worden indien nodig verwisseld. Omdat er geen EX B,D +instructie is wordt dit met een klein truukje gedaan, L +wordt daarbij als hulpregister gebruikt. + +``` +CHECK2: LD A,E + CP C + JR NC,SAVE + LD L,E + LD E,C + LD C,L ; verwissel C en E + +SAVE: LD (BEGIN),BC + LD (EIND),DE +``` + +Ook C en E zijn nu gecheckt en indien nodig verwisseld, +vervolgens worden de co�rdinaten opgeslagen voor later +gebruik. + +``` +; bereken hoogte + + LD A,E + SUB C + INC A ; A=aantal regels + LD (HOOGTE),A +``` + +Dit stukje spreekt eigenlijk voor zich, de hoogte van het +blok waarvan de blink mode aan of uit gezet gaat worden +wordt hier uitgerekend en opgeslagen. + +``` +; bereken beginadres + + LD HL,0 + XOR A + CP C + JP Z,ZETWEG + LD DE,10 + LD B,C +TELOP: ADD HL,DE + DJNZ TELOP +ZETWEG: LD DE,2048 ; beginadres blinktabel VRAM + ADD HL,DE + LD (BEGADR),HL +``` + +C bevat de bovenste regel van het blok waarvan we de +"blinkstand" gaan wijzigen, het beginadres van deze regel +wordt berekend. Hiervoor wordt C vermenigvuldigd met 10, +want elke regel van 80 karakters neemt 80 bits = 10 bytes in +beslag. Voor het vermenigvuldigen wordt de methode van +herhaald optellen gebruikt. Het zo berekende adres wordt bij +het startadres van de blinktabel in het VRAM opgeteld. Een +speciaal geval hebben we als C=0, als we hierop niet +speciaal zouden checken zou bij C=0 het verkeerde beginadres +(namelijk 2048 + 10) worden genomen. Het gevonden beginadres +wordt opgeslagen voor later gebruik. + +``` +; wis masker + + LD HL,MASKER + LD B,10 +LEEG: LD (HL),0 + INC HL + DJNZ LEEG +``` + +Ik heb voor deze routine een systeem bedacht waarbij er +eerst een masker wordt aangemaakt, dat vervolgens over de +juiste regels van de blink tabel wordt geAND of geORd. Eerst +wordt dit masker leeg gemaakt, d.w.z. gevuld met nullen. Het +belangrijkste en ingewikkeldste gedeelte van de routine is +het maken van het masker. + +``` +; maak masker + +; bepaal eerste byte in masker die moet worden aangepast + + LD A,(BEGIN+1) ; linkse X coordinaat + LD HL,MASKER + SRL A + SRL A + SRL A ; A=A/8 + LD C,A + LD B,0 ; LD BC,A + ADD HL,BC ; sla bytes over +``` + +Hier wordt aan de hand van de linker x coordinaat bepaald +welke bytes aan de linkerkant van het masker kunnen worden +overgeslagen. Bijvoorbeeld: linker x coordinaat = 10, dan +hoeft met de linker 8 posities niets te gebeuren en is het +masker daar dus 0. + +``` +; bepaal eerste bit in die byte die moet worden aangepast + + LD A,(BEGIN+1) + AND 7 ; A=bitnummer + OR A + JP Z,SPEC2 ; nog een speciaal geval! + LD B,A + LD A,255 ; alle bits 1 +MAAK0: SRL A ; maak bit 0 en schuif + DJNZ MAAK0 + LD (HL),A ; zet byte weg +BACK: LD (VLGND),HL +``` + +Hier wordt het al wat moeilijker. We halen wederom de linker +x co�rdinaat op en bekijken daarvan alleen de drie laagste +bits, dit het bit nummer aangeven. Hiermee wordt het masker +aan de linkerkant gemaakt. We maken hiervoor een byte +11111111 en schuiven met het juiste aantal SRL instructies +de juiste hoeveelheid nullen erin (aan de linkerkant). Stel +de linker x co�rdinaat is 3, dan moet het masker dus worden + +00011111 masker + +01234567 x co�rdinaat + +Dat zijn precies drie nullen. Een uitzondering moet worden +gemaakt als er helemaal niet geschoven moet worden, daarvoor +wordt er naar SPEC2 gesprongen. SPEC2 maakt het masker +11111111, en springt dan naar BACK. Op (HL) wordt het +zojuist berekende masker neergeset, in (VLGND) wordt de +waarde van HL bewaard. + +``` +; bepaal laatste byte in masker die moet worden aangepast + +ACHTER: LD A,(EIND+1) ; rechtse x coordinaat + LD B,A + LD A,79 + SUB B + LD HL,MASKER+9 + SRL A + SRL A + SRL A ; a=a/8 + LD C,A + LD B,0 + OR A ; wis carry (voor SBC) + SBC HL,BC ; laatste byte + LD (LAATS),HL +``` + +Hier wordt gekeken welke bytes we aan de rechterkant kunnen +overslaan omdat daar toch niets verandert. Met SRL +instructies wordt het aantal bytes uitgerekend, het gevonden +adres wordt in (LAATS) bewaard. + +``` +; maak gebied na byte links t/m byte rechts FF + + LD DE,(VLGND) + RST &H20 ; vergelijk DE met HL + JP Z,SPECIA ; speciaal geval! +MAAKFF: LD (HL),255 + DEC HL + RST &H20 + JP NZ,MAAKFF +``` + +Bovenaan staat al precies wat dit stukje doet. De bytes van +(VLGND)+1 t/m (LAATS) worden 255 gemaakt, het gedeelte +tussen de linker- en de rechtergrens moet immers allemaal +worden "geblinkt". Ook hier weer een speciaal geval: als +alles zich in een byte afspeelt, dus (VLGND) = (LAATS), dan +moet deze byte op een aparte manier worden bepaald (zie bij +het label SPECIA) en rest van de bytes blijft 0. + +``` +; bepaal laatste bit in die byte die moet worden aangepast + + LD A,(EIND+1) + AND 7 ; a=bitnummer + XOR 7 ; a=7-a + JP Z,INVERT ; masker klaar + LD B,A + LD A,255 ; alle bits 1 +MAAK_0: SLA A ; maak bit 0 en schuif + DJNZ MAAK_0 + LD HL,(LAATS) + LD (HL),A ; zet laatste byte weg +``` + +Hier wordt aan de rechterkant de juiste hoeveelheid nullen +toegevoegd. Eerst wordt weer het bitnummer berekend. Omdat +we het nu van de rechterkant bekijken is de XOR instructie +nodig. Het masker is nu klaar. + +``` +; inverteer masker als MODE=0 (wissen) + +INVERT: LD A,(MODE) + OR A + JP NZ,POKE + LD HL,MASKER + LD B,10 +INVER2: LD A,(HL) + XOR 255 + LD (HL),A + INC HL + DJNZ INVER2 +``` + +Het masker dat we hebben gemaakt bevat een 0 op posities die +hetzelfde moeten blijven en een 1 op posities die moeten +veranderen. Voor het aanzetten van de blinkmode is dit +precies goed, we kunnen het masker dan gewoon over de juiste +regels in de blink tabel ORren. Het uitzetten van de +blinkmode gaat echter met AND, en daar moeten de bits juist +1 zijn om de blinkstand niet te laten veranderen. Vandaar +dat hele masker geXORd wordt als (MODE)=0. + +``` +; masker is klaar, zet het over de blinktabel + +POKE: LD A,(HOOGTE) + LD B,A +POKE1: PUSH BC + LD HL,(BEGADR) + LD DE,BUFFER + LD BC,10 + CALL LDIRMV ; kopieer regel uit VRAM + ; naar BUFFER +``` + +Het B register bevat het aantal regels waarover het masker +moet worden gezet. We maken namelijk een lus met DJNZ. Met +een CALL LDIRMV wordt een regel uit de blink tabel in het +VRAM naar een buffer in het RAM gekopieerd. + +``` + CALL CALCUL ; bereken nieuwe data + LD DE,(BEGADR) + LD HL,BUFFER + LD BC,10 + CALL LDIRVM +``` + +Met CALL CALCUL wordt het masker er overheen gezet, +vervolgens wordt de nieuwe regel van de blinktabel met een +LDIRVM in de blinktabel in het VRAM gezet. + +``` + LD HL,(BEGADR) + LD BC,10 + ADD HL,BC + LD (BEGADR),HL + POP BC + DJNZ POKE1 + + RET ; einde hoofdroutine +``` + +Het nieuwe adres in de blinktabel in het VRAM wordt berekend +en weggezet, einde van de DJNZ lus. Met een RET besluiten we +de hoofdroutine. + +``` +; zet het masker over de buffer + +CALCUL: LD A,(MODE) + OR A + JP Z,WIS +``` + +Eerst wordt gekeken of het masker moeten ORren of ANDen. +Vervolgens wordt naar de juiste routine gesprongen. + +``` +ZET: LD HL,MASKER + LD DE,BUFFER + LD B,10 +ZET1: LD A,(DE) + OR (HL) + LD (DE),A + INC DE + INC HL + DJNZ ZET1 + RET +``` + +Hier wordt het masker over de buffer geORd. Verdere uitleg +overbodig. + +``` +WIS: LD HL,MASKER + LD DE,BUFFER + LD B,10 +WIS2: LD A,(DE) + AND (HL) + LD (DE),A + INC DE + INC HL + DJNZ WIS2 + RET +``` + +Hier wordt het masker over de buffer geAND. Verdere uitleg +overbodig. + +``` +; speciaal geval: zowel begin als eind van breedte +; ligt in 1 byte + +SPECIA: LD HL,(VLGND) ; adres in masker + LD A,(EIND+1) + AND 7 ; a=bitnummer + XOR 7 ; a=7-a + JP Z,SPEC3 ; NOG een speciaal geval! + LD B,A + LD A,255 ; alle bits 1 +MAK__0: SLA A ; maak bit 0 en schuif + DJNZ MAK__0 + LD C,A ; mini-masker +BACK2: LD A,(HL) + AND C ; bereken juiste byte + LD (HL),A + JP INVERT ; ga verder met + ; normale routine +``` + +Dit is de speciale routine waar ik het al eerder over had. +Dit komt voor als de beide x co�rdinaten in een byte liggen. +Stel de linker x is 3 en de rechter x 4. Dan was de eerst +byte van het masker al 00011111, zoals we eerder hadden +gezien. De 9 andere bytes van het masker zijn gewoon 0 en +dus al goed. We moeten nu alleen nog drie nullen aan de +linkerkant van de eerst byte toevoegen. Dit kan niet met +schuiven, omdat dan de linkerkant verloren gaat. We +berekenen daarom dezelfde byte die we nodig zouden hebben +als de x co�rdinaten niet in dezelfde byte zouden zitten, +dit is dus 11111000. Vervolgens ANDen we die over de oude +byte, en klaar is Kees!! Het masker is nu ook klaar. + +``` +; nog twee speciale gevallen! + +SPEC2: LD (HL),255 + JP BACK + +SPEC3: LD C,255 + JP BACK2 +``` + +Hier worden de gevallen opgelost waarbij helemaal geen nul +moet worden ingeschoven. Door de constructie met een DJNZ +lus wordt deze lus namelijk ook doorlopen als het aantal te +verschuiven bits gelijk is aan 0. Dit vangen we af met +voorwaardelijke sprongen en deze twee kleine routinetjes. + +``` +; data gebied + +BEGIN: DS 2 +EIND: DS 2 +MODE: DS 1 +HOOGTE: DS 1 +BEGADR: DS 2 +VLGND: DS 2 +LAATS: DS 2 +MASKER: DS 10 +BUFFER: DS 10 +``` + +Tot slot wordt het datagebied nog gedefinieerd. De routine +is nu helemaal klaar!!! + + +## B L I N K B A L + +In het softwaremenu vindt u onder de naam "BLINKBAL.BAS" een +simpel spelletje computertennis, dat gebruikt maakt van de +vier nieuwe BASIC commando's. + + +## T E N S L O T T E + +Best een ingewikkelde routine om te schrijven, maar zeer +handig in het gebruik. In machinetaal nooit meer ingewikkeld +rekenen als de blink mode gebruikt wordt, en in BASIC wordt +het bovendien een heel stuk sneller. + +Veel plezier met deze vier nieuwe BASIC commando's! + +Stefan Boer \ No newline at end of file diff --git a/sunrise_special/2/Ledjes.md b/sunrise_special/2/Ledjes.md new file mode 100644 index 0000000..c46c951 --- /dev/null +++ b/sunrise_special/2/Ledjes.md @@ -0,0 +1,324 @@ +# L E D J E S + + +Zoals u weet heeft de turbo R een schitterende rij ledjes. +Van deze zes ledjes zijn vier eenvoudig met I/O poorten aan +te sturen. Het power ledje is volgens mij helemaal niet aan +te sturen, en de aansturing van het "FDD IN USE" ledje is +bij mij onbekend. Als er lezers zijn die dit wel weten, +schrijf dan even een briefje naar de Sunrise postbus. + +Met de ledjes kun je leuke dingen doen. Ze zijn voorbeeld +geschikt voor een simpele output indicator voor muziek, of +een simpele input indicator voor samples. + + +## L E D J E S S H O W + +Hier doen we er iets anders mee, we laten de ledjes op de +interrupt een bepaald patroontje uitvoeren, wat er heel leuk +uitziet. + +In het softwaremenu vindt u het programma LED.BAS, dat +eigenlijk weinig anders doet dan een BLOAD"LED.BIN",R. Deze +routine hangt zichzelf aan de interrupt en geeft vervolgens +de besturing weer terug aan BASIC. + +We gaan nu de assemblerlisting van LED.BIN bespreken. Deze +assemblerlisting staat ook als LED.ASC op de disk. Zoals +gebruikelijk onderbreek ik de listing regelmatig voor +uitgebreide uitleg. + +``` +; L E D . A S M +; Show met de ledjes van de MSX turbo R +; Alleen turbo R!!! +; Door Stefan Boer 21/04/92 - 21/05/92 - 19/10/92 - 25/10/92 +; Sunrise Special #2 - (c) Stichting Sunrise 1992 +; Eventueel op &HD006-&HD007 beginadres tabel POKEn +; &HD000 aanroepen om te starten +; &HD003 aanroepen om te stoppen +; Commando struktuur: (binair) +; 0 - - - C K P R --> lampjes besturen +; C=caps, K=kana, P=pause, R=R800 +; 1 T T T T T T T --> wachttijd instellen (dus 128+tijd) +; 1 1 1 1 1 1 1 1 --> einde tabel (&HFF) + +HOOK: EQU &HFD9F ; H.TIMI +WRTPSG: EQU &H93 ; BIOS PSG register schrijven + ; (voor kana led) +RDPSG: EQU &H96 ; BIOS PSG register lezen + ; (voor kana led) +WACHT: EQU 5 ; default wachttijd + + ORG &HD000 + + JP INIT ; initialiseer en buig int af + JP EXIT ; herstel interrupt + +ST_TAB: DW TABEL ; beginadres aan routine + ; doorgeven +AD_TAB: DS 2 ; ruimte om huidige plaats + ; in tabel op te slaan +W_A7: DS 1 ; ruimte opslag poort &HA7 +TIME: DB WACHT ; wachttijd +TELLER: DS 1 ; ruimte om tijd bij te houden +``` + +De ledjes show wordt gestart door adres &HD000 aan te +roepen, en weer gestopt door &HD003 aan te roepen. Op ST_TAB +(adres &HD006 en &HD007) kan ook een ander adres worden +gezet, zodat het startadres van de tabel met de data met +twee simpele POKEs kan worden verwijderd. De default +wachttijd is 5, dit betekent dat om de vijf interrupts de +"stand" van de ledjes wordt gewijzigd. + +``` +INIT: LD HL,HOOK + LD DE,OLDHOK + LD BC,5 + LDIR ; bewaar oude hook + DI + LD A,&HC3 + LD (HOOK),A + LD HL,LEDPRG + LD (HOOK+1),HL ; zet JP HOOK op &HFD9F + LD HL,(ST_TAB) ; startadres tabel + LD (AD_TAB),HL ; init pointer + LD A,WACHT + LD (TIME),A ; zet default wachttijd + XOR A + LD (TELLER),A ; teller op 0 zetten + EI + RET +``` + +Dit is de initialisatieroutine. Eerst wordt de oude hook +bewaard, dit is nodig voor het terugzetten van de oude hook +en bovendien zijn zo geneste hooks mogelijk. De oude hook +wordt daarvoor aangeroepen nadat onze routine is +afgehandeld. + +De adrespointer wordt geinitialiseerd door het startadres +van de tabel in te vullen. Bovendien wordt de default +wachttijd ingesteld, en wordt de teller die bijhoudt hoeveel +interrupts er al zijn geweest op 0 gezet. + +``` +EXIT: DI + LD HL,OLDHOK + LD DE,HOOK + LD BC,5 + LDIR ; herstel oude hook + EI + RET +``` + +Hiermee wordt de ledjes show stopgezet, de oude hook wordt +weer hersteld. + +``` +LEDPRG: PUSH AF ; verplicht bij gebruik &HFD9F + LD A,(TIME) + LD HL,TELLER + INC (HL) ; teller verhogen + CP (HL) ; klaar met wachten? + JP NZ,ENDINT ; nee, dan einde interrupt + XOR A + LD (HL),A ; teller op 0 zetten +``` + +Bij binnenkomst wordt eerst AF bewaard. Dit is verplicht als +je de routine onder BASIC wilt gebruiken!! Anders werkt ON +SPRITE GOSUB en het opvragen van statusregister 0 niet meer +goed. AF bevat namelijk de waarde van statusregister 0, die +wordt pas NA het aanroepen van &HFD9F opgeslagen. + +Dit stukje code zorgt ervoor dat steeds het juiste aantal +interrupts wordt overgeslagen. A wordt geladen met (TIME), +het aantal interrupts dat moet worden overgeslagen, en +(TELLER) wordt met ��n verhoogd. Is de juiste waarde nog +niet bereikt, dan wordt de interrupt be�indigd door naar +ENDINT te springen. Anders wordt de teller op 0 gezet en +gaan we verder met de rest van de routine. + +``` + LD HL,(AD_TAB) ; adres commando inlezen +GETCMD: LD A,(HL) ; haal commando op + CP 255 ; einde tabel? + JP Z,EINDE + BIT 7,A ; chtime of normaal commando? + JP NZ,CHTIME ; CHange TIME + LD C,A + INC HL + LD (AD_TAB),HL ; nieuwe pointer wegzetten +``` + +Hier wordt eerst het commando opgehaald. Is dit gelijk aan +255, dan is het einde van de tabel bereikt en wordt naar +EINDE gesprongen (er wordt weer aan het begin van de tabel +opnieuw begonnen). Is bit 7 gezet, dan betekent dit dat de +wachttijd veranderd wordt. Ook hiervoor is een speciale +routine. + +Anders is het een getal tussen 0-15 dat de gewenste stand +van de ledjes weergeeft. Dit getal wordt in C bewaard en de +pointer wordt naar de volgende positie in de tabel +verplaatst. + +``` +; Commando uitvoeren +; A-register: 0 - - - C K P R +; C=caps, K=kana, P=pause, R=R800 +; 0=uit, 1=aan + + IN A,(&HAA) + RES 6,A + BIT 3,C ; caps aan/uit? + JR NZ,CAPS + SET 6,A ; caps uit +CAPS: OUT (&HAA),A +``` + +Dit stukje code bestuurd het caps lampje, dat wordt bestuurd +door bit 6 van poort &HAA. Bit 6 heeft overigens een inverse +werking, als het bit aan is, is het ledje uit! Eerst wordt +poort &HAA uitgelezen. Bit 6 wordt alvast gewist, zodat het +lampje aangaat. Dan wordt bit 3 van C gelezen. Is dit bit +aan, dan is de waarde van het A register al goed en wordt +die bij het label CAPS: naar poort &HAA gestuurd. Anders +wordt bit 6 eerst gezet (ledje uit). + +``` + LD A,15 + CALL RDPSG + RES 7,A + BIT 2,C ; kana aan/uit? + JR NZ,KANA + SET 7,A ; kana uit +KANA: LD E,A + LD A,15 + CALL WRTPSG +``` + +Het kana lampje zit op register 15 van de PSG! Bit 7 +bestuurd het led, ook dit bit heeft een inverse werking. +Eerst wordt register 15 van de PSG gelezen via de BIOS. +Vervolgens wordt via dezelfde methode als bij het caps +lampje bit 7 op de juiste wijze veranderd en vervolgens +wordt register 15 via de BIOS met de nieuwe waarde +beschreven. + +``` + XOR A ; pause en R800 led uit + BIT 1,C ; pause aan/uit? + JR Z,R800 + SET 0,A ; pause led aan +R800: BIT 0,C ; R800 aan/uit? + JR Z,WR_A7 + SET 7,A ; R800 led aan +WR_A7: OUT (&HA7),A +``` + +Het R800 ledje en het PAUSE ledje zitten allebei op I/O +poort &HA7. Het R800 led zit op bit 0, het PAUSE led op bit +7. Omdat beide ledjes op dezelfde poort zitten, sturen we +deze uiteraard ook maar ��n keer uit. Eerst wordt met A +gelijk gemaakt aan 0 met een XOR A. Vervolgens worden de +bits 0 en 7 van A aan de hand van bit 0 en 1 van C indien +nodig aangezet. Tenslotte wordt de waarde naar poort &HA7 +gestuurd. + +``` +ENDINT: POP AF ; einde introutine, herstel AF + ; (=S#0 voor BASIC) +OLDHOK: RET ; hier komt oude interrupt + RET + RET + RET + RET +``` + +Einde van de hoofdroutine. Aan het begin van de routine heb +ik al uitgelegd waarom AF moet worden bewaard. Over de +RETjes wordt door de initialisatieroutine de oude interrupt +hook neergezet. Hierdoor zijn geneste interrupts mogelijk, +en kan er bijvoorbeeld MoonBlaster muziek worden afgespeeld +tijdens de ledjes show. + +``` +; Commando 128+tijd (1-127) verandert wachttijd + +CHTIME: RES 7,A ; wis bit 7 + LD (TIME),A ; nieuwe wachttijd + INC HL + JP GETCMD ; ga verder met volgende cmd +``` + +Hier wordt een "change time" commando afgehandeld. Na het +instellen van de nieuwe wachttijd wordt weer direct verder +gegaan met het volgende commando. + +``` +; Commando &HFF: begin opnieuw in tabel + +EINDE: LD HL,(ST_TAB) + LD (AD_TAB),HL ; zet adres op begin tabel + JP GETCMD ; ga verder met eerste cmd +``` + +Hier wordt het "einde van de tabel" commando afgehandeld. De +adrespointer wordt weer op het begin van de tabel gezet en +er wordt direct verdergegaan met het volgende commando. + +``` +; tabel met commando's, vergeet niet 255 laatste data + +TABEL: DB 128+10,15,0,15,0,15,0,15,0,15,0,15,0 + DB 5,10,5,10,5,10,5,10,5,10,5,10,5,10,0 + DB 15,0,15,0,15,0,15,0 + DB 1,3,7,15,14,12,8,0,8,12,14,15,7,3,1,0 + DB 3,0,3,0,12,0,12,0,3,0,3,0,12,0,12,0 + DB 128+5,1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2,1 + DB 2,4,8,4,2,1,2,4,8 + DB 4,2,1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2,1,255 +``` + +Deze tabel bevat voorbeelddata. Deze data is als volgt +opgebouwd: +``` +MSB 7 6 5 4 3 2 1 0 LSB + + 0 - - - CAPS KANA PAUSE R800 + +of 1 --------------wachttijd-------------- +``` + +En natuurlijk 255 voor het einde van de tabel. Het komt erop +neer dat 128+tijd (0-127) voor het veranderen van de +wachttijd staat en de waardes 1 voor pause, 2 voor R800, 4 +voor kana en 8 voor caps moeten worden opgeteld om een +commando te krijgen dat de stand van de ledjes verandert. +Veel plezier met het zelf maken van leuke patroontjes! + + +## T O T S L O T + +Ik hoop dat dit een leerzaam artikel was. Behalve de +aansturing van de ledjes zijn ook andere technieken aan bod +gekomen zoals het ophalen van een commando, interrupt +afbuigen, een interruptroutine om de zoveel interrupts +uitvoeren, het behandelen van een commando, etc. + +Nog iets grappigs: omdat het natuurlijk erg stom staat als +het ren sha autofire led gewoon door blijft knipperen als de +computer in de pause stand staat, hebben de ontwerpers van +de turbo R dit led aan het pause led geschakeld. Het ren sha +led gaat daardoor uit als het pause led aan is. + +Dit geeft een leuk effect in combinatie met mijn ledjes +routine. Zet de ren sha autofire maar eens aan en start +vervolgens de ledjes routine. Iedere keer als het pause led +aangaat stopt het rensha led! + +Stefan Boer diff --git a/sunrise_special/2/Resource.md b/sunrise_special/2/Resource.md new file mode 100644 index 0000000..a5aa58a --- /dev/null +++ b/sunrise_special/2/Resource.md @@ -0,0 +1,248 @@ +# R E S O U R C E + + +RESOURCE is een CP/M Z80 disk-disassembler die natuurlijk +ook funktioneert onder MSX-DOS. RESOURCE heb ik gedownload +in SUN-BBS. Het programma is al zo'n 10 jaar oud zijn, denk +ik. + +Als je RESOURCE eenmaal doorhebt (en dat probeer ik met dit +artikel te bereiken), kun je er hele leuke dingen mee doen. +Als je weer eens denkt van: "Hmm, dat programma doet iets +wat ik in mijn eigen programma wil gebruiken" hoef je alleen +maar even RESOURCE te gebruiken. + + +## I N S T E L L E N + +RESOURCE heeft een filenaam nodig in de prompt. Je tikt +bijv. in + + RESOURCE COMMAND2.COM + +en je krijgt de volgende tekst op je beeldscherm: + + SUPER CPM Z80 DIS-ASSEMBLER VER 4.00 + ENTER PROGRAM LENGTH: + +Bij de lengte kun je in het begin het beste gewoon op RETURN +drukken. Dan wordt de lengte genomen die in de directory +staat. Verdere uitleg hierover volgt. + +Dan krijg je + + ENTER PROGRAM STARTING ADDRESS: + +voor je ogen. Hier moet je 0100 opgeven. Meestal zal +RESOURCE voor .COM-files worden gebruikt, en die worden +altijd op (#0100) ingeladen en gestart. + +Dan volgt: + + ENTER PROGRAM OFFSET INTO FILE: + +Hier kun je het aantal bytes, die als header gebruikt +worden, instellen. Bij .BIN-files moet je hier 7 invullen. + +De volgende vraag is: + + DO YOU WANT AN ASCII DUMP? + +Als er tekst in de file staat, moet je hier de Y indrukken. + +Bij de volgende vragen druk ik (ook) altijd de Y in: + + DO YOU WANT THE LISTING PASS? + DO YOU WANT THE SOURCE OUTPUT PASS? + DO YOU WANT THE LABLE CROSS REFRENCE PASS? + MAKE ALL INTERNAL TABLE REFRENCES LABLES? + DO YOU WANT TABS USED IN OUTPUT? + LIST OUTPUT TO DISK FILE? + +De werking hiervan is me niet overal geheel duidelijk, maar +mij leverde overal Y het juiste effekt op. (Y was natuurlijk +het eerste dat ik probeerde.) + +Dan volgen er de intrigerende vragen: + + ENTER "BYTE" AREA ADDRESS PAIRS (1 SET PER LINE): + ENTER "WORD" AREA ADDRESS PAIRS (1 SET PER LINE): + +Hier druk ik maar gewoon RETURN in. Ik denk dat je hier in +kunt stellen bij welke gedeelten "DB" en "DW" worden +gebruikt. Als dat zo is, is het handig als je weet waar de +tekst precies staat. Maar daarom heb je "ASCII DUMP" op aan +gezet. + +Helaas moet je al die instellingen telkens opnieuw doen. +Maar daarom kun je dan een batchfile maken die gebruik maakt +van KEYFAKE (ook op deze Special). + + +## S T A R T E N + +Als je alles volgens bovenstaande tekst heb ingevuld krijg +je 1 of 2 files op disk: COMMAND2.ASM en COMMAND2.PRN. De +.ASM-file bevat de pure source. Deze kun je zo weer +assembleren. In COMMAND2.PRN staan allerlei extra dingen. +Het enige dat mij tot nog toe hiervan geboeid heeft is de +ASCII-dump helemaal in het begin van de file. + +Waarschuwing: de grootte van de files kan al gauw enorm +zijn! De disassembleer-tijd is zeer groot. TED +disassembleren kostte mij op mijn turbo R 20 (twintig!) +minuten. De .ASM-file was 300 kB en de .PRN-file 500 kB. Ook +had ik alles op de RAMdisk gedaan (1024 kB intern). + +Als je geen turbo R hebt en je wilt een groot programma (10 +kB is al vrij groot) disassembleren is het aan te raden om +je computer te laten beginnen als je bijv. gaat eten. Als je +dan terugkomt kun je blij zijn als hij klaar is. (Je kunt +natuurlijk ook gaan chatten! Dat is een favoriet +tijdverdrijf van mij.) Houdt rekening met factor 30 a 35 +voor de grootte van de file. Probeer het zoveel mogelijk via +RAMdisk te doen. + + +## V O O R B E E L D + +Als voorbeeld zal ik nu even een machinetaalprogrammaatje +intikken en de geRESOURCEde versie ook afbeelden. + +``` + BDOS: EQU 5 + POINT: EQU #8000 + + LD C,9 + LD DE,TEKST + CALL BDOS + LD HL,POINT + LD B,"K" + LD (HL),B + RST 0 + + TEKST: DB "Dit is een test voor RESOURCE" + DB 13,10,"$" +``` +Ik heb een paar variabelen gebruikt om te laten zien wat +RESOURCE hiervan maakt. + + +## V O O R B E E L D N A R E S O U R C E +``` + ORG 00100H +``` +Dit is het startadres. en dit je weglaten als je met GEN80 +of M80 werkt. +``` + X0005 EQU 00005H +``` +Het BDOS-aanroepadres. Als je met TED werkt kun je het beste +onvoorwaardelijk X0005 door BDOS laten vervangen. + +``` + X0177 EQU 00177H + X017C EQU 0017CH + X017D EQU 0017DH + X018F EQU 0018FH + X0196 EQU 00196H +``` +Deze labels worden in de tekst gebruikt. Alle tekst dien je +toch te vervangen door DB's, dus eigenlijk kunnen deze +labels verwijderd worden. + +``` + LD C,009H + LD DE,T010F + CALL X0005 +``` +De BDOS-aanroep. + +``` + LD HL,08000H + LD B,04BH +``` +Even zien wat er gedaan wordt met gewone veriabelen: hier +komt de "intelligentie" van RESOURCE te voorschijn. Er wordt +verschil gemaakt tussen tekst (zie boven) en een gewoon +adres. + +``` + LD (HL),B + RST 000H +``` +Bij RST's worden uiteraard geen labels gebruikt. + +``` + T010F: LD B,H + LD L,C + LD (HL),H + JR NZ,X017D + LD (HL),E + JR NZ,X017C + LD H,L + LD L,(HL) + JR NZ,X018F + LD H,L + LD (HL),E + LD (HL),H + JR NZ,X0196 + LD L,A + LD L,A + LD (HL),D + JR NZ,X0177 + LD B,L + LD D,E + LD C,A + LD D,L + LD D,D + LD B,E + LD B,L + DEC C + LD A,(BC) + INC H + END +``` +Dit is de tekst. Tekst is te herkennen aan het voorkomen van +relatief veel JR NZ's, dat is het gevolg van spaties. Ook +bestaat het vrijwel helemaal uit onzinnige LD's. +Tenslotte wordt elke source be�indigd met END. + + +## G E B R U I K + +Het bovenste gedeelte van de .PRN-file kun je het beste +uitprinten. Dan kun je de onzin-instructies heel makkelijk +vervangen door de juiste tekst. + +De gebruikte labels zijn als volgt opgebouwd: eerst een +letter met de vermoedelijke betekenis van het label, dan het +adres waar het label stond bij de originele file. + +De volgende letters ben ik al tegengekomen: + +T: tekst. +A: sprong-adres in het programma zelf +Y: onopgelost label, meestal een CALL-adres zoals de BDOS +X en Y: onopgelost label (?) +D: vermoedelijk een adres buiten de programma-code, maar wat + toch aangeroepen wordt met "JP". + + +Als je een label doorhebt, kun je het onvoorwaardelijk door +een duidelijk label laten vervangen met TED. + +Ik ga zelf altijd de hele source na van het begin tot het +einde. Als ik dat gedaan heb, kan ik de source aanpassen en +in mijn eigen programma's gebruiken. + +Vragen of opmerkingen (of fanmail) naar de Sunrise postbus +sturen t.a.v. Kasper Souren. Ik zou graag weten hoe ik +bepaalde gedeelten automatisch door DB's kan laten omzetten. +Dat zou heel veel werk schelen. Op deze disk staan +RESOURCE.COM en RESOURCE.BAT, een kleine batchfile die +gebruik maakt van KEYFAKE om RESOURCE automatisch in te +stellen (even aanpassen voor MSX-DOS 1). + +Kasper Souren + diff --git a/sunrise_special/2/cdd.md b/sunrise_special/2/cdd.md new file mode 100644 index 0000000..9aa580c --- /dev/null +++ b/sunrise_special/2/cdd.md @@ -0,0 +1,244 @@ +# C D D + + +CDD is een afkorting voor Change Drive and Directory. Dit +programma heb ik geschreven omdat ik anders altijd met 2 +commando's in een batchfile moest werken. De interne CD kan +niet de default drive veranderen: als je een driveletter +opgeeft wordt de directory van die drive veranderd. + +Het programma heeft alleen nut op een harddisk. Het kost +altijd een cluster en het moet van disk worden ingeladen. En +boven alles: een diskette van 720 kB is veel te klein en +langzaam om met subdirectory's te werken. Meer dan 2 +diskdrives heeft toch bijna niemand. + + C: + CD \MUSIC\SME3 + +wordt met CDD.COM + + CDD C:\MUSIC\SME3 + + +## W E R K I N G + +Op deze disk staan de files CDD.GEN en de al kant en klare +versie CDD.COM. +Hier volgt een bespreking en uitleg van de gebruikte +methodes. + +``` +LOCATE: MACRO @X,@Y + DB 27,"Y",32+@Y,32+@X + ENDM +``` + +Zie de tekst over macro's, ook op deze Special. + + +## T E S T E N O P M S X - D O S 1 + +``` + LD A,(#F313) ;DOS-versie + OR A ;CP 0 + JR Z,DOS1 ;0 -> DOS1 +``` + +Op adres #F313 staat een getal dat door MSX-DOS 2 gebruikt +wordt. Hier zet hij het versienummer in BCD neer. MSX-DOS +2.30 en 2.31 gebruiken hetzelfde getal: #23. + +MSX-DOS 1 laat er gewoon 0 staan. OR A verandert niks aan A, +maar be�nvloed het flag-register aan de hand van de waarde +van A. AND A heeft hetzelfde effect, maar wordt, volgens mij +door gewenning, bijna nooit gebruikt. + + +## I S E R W E L I N P U T ? + +``` + LD HL,#0080 ;DMA-adres + LD A,(HL) ;Lengte + OR A ;CP 0 + JR Z,Expl ;Geen input? Uitleg +``` + +Er wordt even gecontroleerd of er wel een input is achter +CDD. +Ik gebruik de plaats (adres #0080) die door ASCII wordt +aanbevolen. Op adres #005C staan ook de tekens die ik nodig +heb, en die zijn makkelijker te gebruiken. + +Ik zet het adres in HL omdat dat korter is als ik het nog +eens nodig heb (H blijft toch #00): + +``` + INC L ;L <- #82 + INC L + LD C,A ;Lo-byte (A: lengte) + LD B,0 ;Hi-byte + LD A,":" + CPIR ;Zoek dubbele punt +``` +CPIR doet het volgende: + A - (HL) + HL <- HL + 1 + BC <- BC - 1 + Herhaal tot A=(HL) of BC=0 + +Er wordt in dit geval gezocht naar ":", het teken na de +driveletter. BC krijgt de lengte van de invoer. En HL had +\#0082. Door het gebruik van CPIR mag er ook iets als + + CDD C:\MUSIC\SME3 + +ingevoerd worden. +``` + LD A,B ;BC=0? + OR C + JR Z,Expl ;Ja? Uitleg +``` +Als BC 0 is, is er niks bij CPIR gevonden en wordt er naar +de uitleg gesprongen. +Deze constructie is een stuk korter en sneller dan +``` + LD A,B + OR A + JR Z,Expl + LD A,C + OR A + JR Z,Expl +``` +De werking zal meteen duidelijk zijn, maar het je moet het +wel weten. (Een maand geleden deed ik het zelf nog op de +tweede manier.) + + +## G E B R U I K I N P U T +``` + DEC L ;(HL)=Driveletter + DEC L + LD A,(HL) + AND 255-32 + SUB "A" ;A=Drivenummer + JR C,Error +``` +HL bevatte nog het adres van de dubbele punt plus ��n. Er +moet dus 2 vanaf getrokken worden om tot het adres van de +driveletter te komen. H blijft toch #00. +Dan moet er nog een hoofdletter van gemaakt worden met AND +255-32. (Met dank aan Hans Peeters voor de attentie!) En +wordt er "A" vanaf getrokken om tot een drivenummer te +komen. Als die waarde dan kleiner dan 0 (JR C) is dan is er +iets fout. +``` + INC HL ;HL+=2 (in C) + INC HL ;HL=HL+2 (in BASIC) + PUSH HL ;SP1 + PUSH AF ;SP2 + LD C,#0E ;_SELDSK + LD E,A ;0=A: 1=B: usw. + CALL 5 +``` +Stel eerst HL en A veilig voor het verdere programma +(directory veranderen). En dan de drive veranderen met een +routine uit het CP/M-tijdperk. + +``` + LD A,(#0004) ;Default drive CP/M + LD B,A + POP AF ;SP2 + CP B + JR NZ,DriveErr +``` +Op (#0004) staat het default drivenummer (ook van CP/M). Als +het default drivenummer na het veranderen ongelijk is aan de +input, bestaat de drive niet en wordt er een error-code +gegeven door MSX-DOS 2. + + +## C H A N G E D I R E C T O R Y +``` + POP DE ;SP1 + LD C,#5A ;_CHDIR + CALL 5 + JR NZ,Error + RST 0 ;Einde +``` +Haal HL van de stapel in DE. Dit is korter dan POP HL en EX +DE,HL. Verander van directory en controleer of er nog iets +fout is gegaan. De BDOS van MSX-DOS 2 (van MSX-DOS 1 weet ik +het niet) heeft OR A (CP 0) als laatste instructie voor de +RET. Je kunt dus meteen met een JP NZ,Error of JR NZ,Error +beginnen. De string die BDOS-funktie #5A gebruikt is ASCIIZ +(afgesloten met Zero, 0) en de input op #0080 is ook al +ASCIIZ. (Meer over de BDOS-funkties bij de MSX-DOS 2 cursus +op deze en volgende Specials.) + +RST 0 is tenslotte het einde. RST 0 is maar een byte lang. +Er kan ook met RET teruggekeerd worden, maar dit is +makkelijker bij het debuggen (bij MSX-Debug dan). + +``` +Error: LD B,A +Error2: LD C,#62 ;Return with error + JP 5 +``` +"Return with error-code" keert terug naar MSX-DOS en geeft +een foutmelding als A ongelijk aan 0 is. De fout stond nog +in A en moet in B staan voor "Return with error-code". +Error2 is als label erbij gezet voor: +``` +DriveErr: LD B,#DB + JR Error2 +``` +\#DB is de fout-code voor "Drive does not exist". + +``` +Expl: LD DE,T_Expl +Expl1: LD C,9 ;String output + JP 5 +``` +Geeft uitleg d.m.v. de standaard BDOS-output zodat het nog +te pipen en redirectioneren (?!) is. JP kan ook gebruikt +worden in plaats van CALL en RET. MSX-DOS heeft altijd 0 op +de stapel staan en een RET als einde heeft hetzelfde effect +als RST 0. + +``` +DOS1: LD DE,T_DOS1 + LD C,9 ;String output + CALL 5 + LD C,1 ;Console input + CALL 5 + JR Expl +``` +Even een tekstje voor MSX-DOS 1 gebruikers laten zien, +wachten op een toets en terug naar uitleg. + +``` +T_Expl: DB 12 + DB "Change Drive and Directory",13,10 + DB "--------------------------",13,10,10 + DB "Usage: CDD d:[dir]",13,10,10 + DB "d: drive",13,10 + DB "dir subdirectory",13,10,10 + LOCATE 0,56 + DB "(f) WSL - Kasper Souren" + LOCATE 0,10 + DB "$" + +T_DOS1: DB 12,"Jammer, dit programma werkt alleen " + DB "met MSX-DOS 2 of hoger.",13,10,10 + DB "Druk op een toets. $" +``` +De teksten. Code 12 is hetzelfde als CLS, LOCATE is een +macro dat werkt met de VT-52 code voor LOCATE. Code 10 is +linefeed en als je een regel wilt overslaan moet je 2 keer +10 gebruiken. De streepjes die ik in het echte programma +gebruik worden niet geaccepteerd door de tekstroutine van +Sunrise Special dus heb ik die maar vervangen voor andere +streepjes. De "(f)" staat tenslotte voor Freeware. + +Kasper Souren diff --git a/sunrise_special/2/redirection.md b/sunrise_special/2/redirection.md new file mode 100644 index 0000000..cae52dd --- /dev/null +++ b/sunrise_special/2/redirection.md @@ -0,0 +1,147 @@ +# R E D I R E C T I O N E N P I P I N G + + +MSX-DOS 2 kent interessante mogelijkheden voor programma's +die de BDOS-calls gebruiken voor input en output. BDOS is +een afkorting van Basic Disk Operating System. Alle +CP/M-programma's (en dat zijn er nogal wat!), de meeste +commando's en MSX-DOS programma's werken met de BDOS. Dat +betekent dat ze niet al te snel zijn (op 3.58 MHz dan), maar +wel met redirection en pipelining kunnen werken. + +Allereerst moet je dan wel iets weten van het volgende +onderwerp: + + +## D E V I C E S + +Devices, of voor de puristen onder ons apparaatnaman, zijn +invoer- of uitvoermethodes. Ik zal ze kort omschrijven: +CON Uitvoer naar het beeldscherm en invoer van het + toetsenbord. +NUL Geen invoer en geen uitvoer. Handig om het scherm leeg + te houden. +PRN Invoer en uitvoer naar de printer. +LST Idem. +AUX Dit is met ADDAUX.COM, een programma van DOS2-tools van + ASCII te gebruiken als invoer van de RS-232C poort en + uitvoer naar de RS-232C poort. Alleen de standaard + interface werkt hiermee. Dus geen aangepast modem + zonder de RS-232C ROMs. + +## R E D I R E C T I O N + +MSX-DOS kan ervoor zorgen dat de standaard input- en +outputroutines van de BDOS niet met het scherm en het +toetsenbord werken, maar met (tekst)files of andere devices +dan CON. Door een van de symbolen <, > of >> toe te voegen +achter een filenaam zal de invoer en uitvoer niet via CON +verlopen, maar op een andere wijze: +< Dit zorgt ervoor dat de input van een commando/file + veranderd wordt. De erop volgende filenaam/device zal + dan de input van het toetsenbord vervangen. +> De uitvoer van een commando zal gestuurd worden naar de + filenaam die erop volgt. De file wordt opnieuw geopend, + als die al bestaat, en er zal dus helemaal aan begin + begonnen worden met de uitgevoerde tekst. +>> De uitvoer zal naar de filenaam gestuurd worden + gestuurd. Het bestand zal dan gewoon blijven bestaan, de + uitgevoerde tekst zal ACHTER het bestand komen. + +De redirection-symbolen zullen worden opgevangen door DOS2. +Ze zullen niet worden gebruikt door het commando. Het is +evenwel ook uit te zetten d.m.v. het enironment item REDIR. +Standaard staat dit op ON. Maar met SET REDIR=OFF kun je +toch de redirection (en pipelining) tekens gebruiken voor +een commando. Dan kun je logischerwijze geen redirection of +pipelining meer gebruiken. + + +Voorbeelden: + +COPY A:*.* B:>NUL +Eigenlijk is dit natuurlijk alleen handig bij 2 drives. Want +de melding om van disk te wisselen zal ook niet op het +scherm worden afgedrukt. + +Ook kun je heel makkelijk een directory afdrukken: +DIR/W>PRN + + +## B A T C H F I L E S + +Als de in- of uitvoer van een batchfile geredirectioned is, +zal die redirection betrekking hebben op alle commando's in +die batchfile. Alleen de commando's in de batchfile die al +een redirection hebben zullen niet volgens de +batch-direction werken. Even een voorbeeldje: +Het batchbestand TEST.BAT: + +ECHO Deze tekst wordt naar de printer gestuurd.>PRN +ECHO Het is nog onbekend waar deze tekst komt. + +Bij het intikken van TEST>NUL zal "Deze tekst wordt naar de +printer gestuurd." op papier komen te staan, als de printer +er is, online staat en er papier in zit. En "Het is nog +onbekend waar deze tekst komt." zal gewoon "verdwijnen". + + +## P I P E L I N I N G + +Het is niet alleen mogelijk om de in- en output van een +commando naar een device of file te sturen, maar ook om de +uitvoer van het ene commando naar een ander commando te +"pipen". + +Met deze optie zijn diverse leuke dingen te bedenken. Zoals +een programma wat het aantal letters, woorden, regels en +pagina's telt. + +Piping wordt aangeduid met het symbool |. Het commando dat +links van | staat zal eerst worden uitgevoerd, en de uitvoer +daarvan zal worden doorgevoerd naar de invoer van het +commando achter |. De outvoer van het eerste commando zal in +een file worden gezet, die dan door de invoer van het 2e +commando zal worden gelezen. + +De naam van die file is %TEMPxxx.$$$ waarbij xxx een getal +is dat ervoor zorgt dat er niet 2 tempfiles dezelfde naam +krijgen (zolang er natuurlijk niet meer dan 1000 temp-files +zijn natuurlijk). De plaats van de files wordt aangeduid +door het environment item TEMP. Het is aan te raden om +hiervoor de RAMdisk te gebruiken, omdat de file wordt +aangemaakt, gelezen en weer gewist. En dat alles merk je +bijna niet met een RAMdisk. Met een gewone diskdrive +natuurlijk wel. Bij harddisk-gebruik kan er natuurlijk ook +een TEMP-directory voor worden aangemaakt. + + +## B A T C H F I L E S + +Het is niet mogelijk om pipelining rechtstreeks met +batchfiles te gebruiken. Maar het is wel mogelijk om een +batchfile te starten met COMMAND2.COM, de batchfile komt dan +achter COMMAND2 en zal dan gewoon werken als een .COM-file. +Noot: Elke keer dat COMMAND2.COM opnieuw wordt gestart kost +dat 1,5 kB van het TPA-geheugen, het geheugen dat MSX-DOS +programma's gebruiken en zo'n 55 kB groot is. + +Voorbeelden: + +ECHO Y|DEL A:*.*>NUL +Nu zal Y worden ingevoerd bij de vraag of alle file gewist +moeten worden van drive A:. Die vraag zal daarbij ook nog +eens niet op het scherm verschijnen door de redirection naar +het NUL-device. +Dit is wel nog te UNDELeten, en het zal geen subdirectory's +beschadigen. Maar veel gemener is: + +ECHO Y|FORMAT d:>NUL +En vul voor d: maar een drive in. Harddisks kunnen zo +(gelukkig (helaas?)) niet geformatteerd worden, daarvoor is +immers FDISK noodzakelijk. + +Zie voor meer voorbeelden de tekst over MSX-DOS 2.31. (Ook +interessant voor mensen zonder een FS-A1GT!) + +Kasper Souren \ No newline at end of file diff --git a/sunrise_special/3/Getdisk.md b/sunrise_special/3/Getdisk.md new file mode 100644 index 0000000..6fbeb38 --- /dev/null +++ b/sunrise_special/3/Getdisk.md @@ -0,0 +1,68 @@ + + G E T D I S K + + + Getdisk is een utility voor harddiskgebruikers om spellen en + programma's die een hele diskette beslaan (waar dus geen + losse files op staan) toch op de harddisk te installeren. + + Getdisk leest namelijk de hele 720 kB diskette in en slaat + hem op als ÇÇn grote file. Met het bijbehorende programma + START.COM kan deze file nu opgestart worden alsof het gewoon + een diskette. Syntax: + + START d:filename.ext + + Dit werkt altijd goed als het betreffende programma normaal + van disk onder MSX-DOS 2 zonder problemen opgestart kan + worden. + + Bij programma's die normaal onder DOS2 vastliepen kan het + soms ook werken, omdat er wat hooks en BIOS routines door + START.COM worden omgebogen om zoveel mogelijk DOS1 + compatible te blijven. + + + M E E R D E R E D I S K S + + Getdisk kan ook spellen van meerdere diskettes aan (maximaal + 10). Deze worden dan samen als ÇÇn grote file opgeslagen. Zo + kost SD Snatcher bijvoorbeeld ongeveer 2 MB aan diskruimte + (3 diskjes). + + Als er tijdens het spelen van het spel van disk gewisseld + moet worden kan dit door een cijfertoets ingedrukt te houden + van 1 tot 9 of 0 (0 = diskje 10) TEGELIJKERTIJD met de actie + die uitgevoerd moet worden om het spel te hervatten. + + Hier bedoel ik mee dat als er op het scherm staat: + + Insert disk 2 and press space. + + Dat dan cijfertoets "2" ingehouden moet worden terwijl je op + de spatiebalk drukt. + + + U S E R D I S K + + Houd er rekening mee dat sommige spellen een userdisk nodig + hebben om data op te saven. Bij deze spellen moet er dus een + extra disk ingevoerd worden bij het uitvoeren van Getdisk, + want de gewone diskdrive is uit het spel nu niet meer te + bereiken! + + + De hele Getdisk-utility bestaat uit de volgende files: + + GETDISK.BAS: de loader van GETDISK.BIN + GETDISK.BIN: de disk naar harddisk omzetter + START.COM : het opstartprogramma voor omgezette files + + Ik hoop dat ik met deze utility enkele harddiskgebruikers + (met een grote harddisk, want het vreet wel ruimte die + diskjes) een plezier doe en mensen zonder harddisk aanmoedig + om een harddisk te kopen, want het is zo heerlijk snel + (zeker op een turbo R). + + Michel Shuqair + \ No newline at end of file