diff --git a/README.md b/README.md index 41ad6c0..4efdbd9 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Happy reading!! | [Assembly cursus 8](future_disk/40/assembly_cursus_8.md) | Arjan Bakker | Future Disk 40 | | [Assembly cursus 9](future_disk/42/assembly_cursus_9.md) | Arjan Bakker | Future Disk 42 | | [Assembly voor beginners](future_disk/30/assembly_voor_beginners.md) | Arjan Bakker | Future Disk 30 | +| [BDOS Foutafhandelingen](sunrise_special/4/bdos_foutafhandeling.md) | Alex van der Wal | Sunrise Special 4 | | [Bits en bull](future_disk/33/bits_en_bull.md) | Tobias Keizer | Future Disk 33 | | [CDD](sunrise_special/2/cdd.md) | Stefan Boer | Sunrise Special 2 | | [Cirkels in ML](future_disk/02/cirkels_in_ml.md) | Jeroen Smael | Future Disk 02 | @@ -27,11 +28,14 @@ Happy reading!! | [Data compressie](future_disk/35/datacompressie.md) | Arjan Bakker | Future Disk 35 | | [Data compressie 2](future_disk/36/datacompressie_2.md) | Arjan Bakker | Future Disk 36 | | [Disk cursus special 1](sunrise_special/1/disk_cursus_special_1.md) | Stefan Boer | Sunrise Special 1 | +| [Easy BDOS](sunrise_special/4/easy_bdos.md) | Alex van der Wal | Sunrise Special 4 | | [File handles](sunrise_special/3/file_handles.md) | Kasper Souren | Sunrise Special 3 | | [Geheugen schakelen](sunrise_special/2/geheugen_schakelen.md) | Stefan Boer | Sunrise Special 2 | | [Geheugen tellen](sunrise_special/1/geheugen_tellen.md) | Stefan Boer | Sunrise Special 1 | | [Getallen printen](sunrise_special/3/getallen_printen.md) | Stefan Boer | Sunrise Special 3 | | [Het rel file formaat](sunrise_special/1/het_rel_formaat.md) | Stefan Boer | Sunrise Special 1 | +| [Hex Printen](sunrise_special/4/hex_printen.md) | Stefan Boer | Sunrise Special 4 | +| [Index registers](sunrise_special/4/index_registers.md) | Stefan Boer | Sunrise Special 4 | | [Interrupt service routines](sunrise_special/2/interrupt_service_routines.md) | Alex van der Wal | Sunrise Special 2 | | [Ledjes](sunrise_special/2/ledjes.md) | Stefan Boer | Sunrise Special 2 | | [Lijntjes](future_disk/42/lijntjes.md) | Arjan Bakker | Future Disk 42 | @@ -56,17 +60,22 @@ Happy reading!! | [Mcode Special 3](future_disk/23/mcode_special_3.md) | Ruud Gelissen | Future Disk 23 | | [Mcode Special 4](future_disk/25/mcode_special_4.md) | Ruud Gelissen | Future Disk 25 | | [Mcode Special 5](future_disk/27/mcodespecial_5.md) | Ruud Gelissen | Future Disk 27 | +| [MSX Audio](sunrise_special/4/msx_audio.md) | Kasper Souren | Sunrise Special 4 | | [MSX Assemblers](sunrise_special/1/msx_assemblers.md) | Alex van der Wal | Sunrise Special 1 | | [MSX-DOS 2 voor machinetaalprogrammeur](sunrise_special/2/msx-dos_2_voor_machinetaalprogrammeurs.md) | Daniel Wiermans | Sunrise Special 2 | | [MSX-DOS2 deel 1](future_disk/25/msx-dos2_deel_1.md) | Tobias Keizer | Future Disk 25 | | [MSX-DOS2 deel 2](future_disk/28/msx-dos2_deel_2.md) | Tobias Keizer | Future Disk 28 | | [MSX-DOS2 deel 3](future_disk/28/msx-dos2_deel_3.md) | Tobias Keizer | Future Disk 28 | | [Muis uitlezen](sunrise_special/1/muis_uitlezen.md) | Alex van der Wal | Sunrise Special 1 | +| [NTM Coordin](sunrise_special/4/ntm_coordin.md) | Kasper Souren | Sunrise Special 4 | | [Paint in ML](future_disk/30/paint_in_ml.md) | Arjan Bakker | Future Disk 30 | | [Pauze toets](sunrise_special/2/pauze_toets.md) | Stefan Boer | Sunrise Special 2 | +| [PCM rechtstreeks](sunrise_special/4/pcm_rechtstreeks.md) | Stefan Boer | Sunrise Special 4 | | [PCM routines van de bios](sunrise_special/2/pcm_routines_van_de_bios.md) | Bernard Lamers | Sunrise Special 2 | | [PCM Sampler](sunrise_special/2/pcm_sampler.md) | Stefan Boer | Sunrise Special 2 | +| [Print routine](sunrise_special/4/print_routine.md) | Kasper Souren | Sunrise Special 4 | | [R800](sunrise_special/1/r800.md) | Stefan Boer | Sunrise Special 1 | +| [Random](sunrise_special/4/random.md) | Kasper Souren | Sunrise Special 4 | | [Rechtstreeks via PCM afspelen](sunrise_special/2/rechtstreeks_via_pcm_afspelen.md) | Pierre Gielen | Sunrise Special 2 | | [Rel assembleren](sunrise_special/1/rel_assembleren.md) | Rudy Oppers | Sunrise Special 1 | | [Resource dis-assembler](sunrise_special/2/resource.md) | Kasper Souren | Sunrise Special 2 | @@ -83,6 +92,17 @@ Happy reading!! | [VDP Cursus 2](sunrise_special/2/vdp_cursus_2.md) | Stefan Boer | Sunrise Special 2 | | [VDP Cursus 3](sunrise_special/3/vdp_cursus_3.md) | Stefan Boer | Sunrise Special 3 | | [VDP Cursus 4](sunrise_special/3/vdp_cursus_4.md) | Stefan Boer | Sunrise Special 3 | +| [VDP Cursus 5](sunrise_special/4/vdp_cursus_5.md) | Stefan Boer | Sunrise Special 4 | +| [VDP Cursus 6](sunrise_special/4/vdp_cursus_6.md) | Stefan Boer | Sunrise Special 4 | +| [VDP Cursus 7](sunrise_special/5/vdp_cursus_7.md) | Stefan Boer | Sunrise Special 5 | +| [VDP Cursus 8](sunrise_special/5/vdp_cursus_8.md) | Stefan Boer | Sunrise Special 5 | +| [VDP Cursus 9](sunrise_special/5/vdp_cursus_9.md) | Stefan Boer | Sunrise Special 5 | +| [VDP Cursus 11](sunrise_special/7/vdp_cursus_11.md) | Stefan Boer | Sunrise Special 7 | +| [VDP Cursus 12](sunrise_special/7/vdp_cursus_12.md) | Stefan Boer | Sunrise Special 7 | +| [VDP Cursus 13](sunrise_special/7/vdp_cursus_13.md) | Stefan Boer | Sunrise Special 7 | +| [VDP Cursus 14](sunrise_special/7/vdp_cursus_14.md) | Stefan Boer | Sunrise Special 7 | +| [VDP Cursus 15](sunrise_special/7/vdp_cursus_15.md) | Stefan Boer | Sunrise Special 7 | +| [VDP Cursus 16](sunrise_special/7/vdp_cursus_16.md) | Stefan Boer | Sunrise Special 7 | ## Basic @@ -95,12 +115,15 @@ Happy reading!! | [Advanced Basic 4](future_disk/33/advanced_basic_4.md) | Arjan Bakker | Future Disk 34 | | [Advanced Basic 5](future_disk/36/advanced_basic_5.md) | Arjan Bakker | Future Disk 36 | | [Advanced Basic 6](future_disk/37/advanced_basic_6.md) | Arjan Bakker | Future Disk 37 | +| [Barcode](sunrise_special/7/barcode.md) | Rob Augusteijn | Sunrise Special 7 | | [Basic Cursus 6](future_disk/17/basic_cursus_6.md) | Tobias Keizer | Future Disk 17 | | [Basic Cursus 8](future_disk/19/basic_cursus_8.md) | Tobias Keizer | Future Disk 19 | | [Basic voor beginners](future_disk/19/basic_voor_beginners.md) | Tobias Keizer | Future Disk 19 | | [Call Kanji](future_disk/21/call_kanji.md) | Tobias Keizer | Future Disk 21 | +| [Circle](sunrise_special/4/circle.md) | Stefan Boer | Sunrise Special 4 | | [Copy in BASIC](future_disk/25/copy_in_basic.md) | Vincent | Future Disk 35 | -| [DIsk IO in BASIC](future_disk/31/disk_io_in_basic.md) | Tobias Keizer | Future Disk 31 | +| [Disk IO in BASIC](future_disk/31/disk_io_in_basic.md) | Tobias Keizer | Future Disk 31 | +| [KUN-BASIC Cursus](sunrise_special/4/kun_basic_cursus.md) | Randy Simons | Sunrise Special 4 | | [Ledjes](future_disk/21/ledjes.md) | Tobias Keizer | Future Disk 21 | | [MSX2+ Schermen in BASIC](future_disk/19/msx2+_schermen_in_basic.md) | Tobias Keizer | Future Disk 19 | | [Muizen in BASIC](future_disk/20/muizen_in_basic.md) | Tobias Keizer | Future Disk 20 | @@ -120,9 +143,11 @@ Happy reading!! | --- | --- | --- | | [Programmeer taal c](sunrise_special/2/programmeer_taal_c.md) | Robert Amesz | Sunrise Special 2 | | [Programmeer taal c 2](sunrise_special/2/programmeer_taal_c_2.md) | Robert Amesz | Sunrise Special 2 | -| [Programmeer taal c 3](sunrise_special/3/de_programmeer_taal_c_deel_3.md) | Robert Amesz | Sunrise Special 3 | -| [Programmeer taal c 4](sunrise_special/3/de_programmeer_taal_c_deel_4.md) | Robert Amesz | Sunrise Special 3 | +| [Programmeer taal c 3](sunrise_special/3/de_programmeertaal_c_deel_3.md) | Robert Amesz | Sunrise Special 3 | +| [Programmeer taal c 4](sunrise_special/3/de_programmeertaal_c_deel_4.md) | Robert Amesz | Sunrise Special 3 | +| [Programmeer taal c 5](sunrise_special/4/de_programmeertaal_c_deel_5.md) | Robert Amesz | Sunrise Special 4 | | [Werken met ASCII C.md](sunrise_special/3/werken_met_ascii_c.md) | Alex Wulms | Sunrise Special 3 | +| [Werken met ASCII C 2.md](sunrise_special/4/werken_met_ascii_c_deel_2.md) | Alex Wulms | Sunrise Special 4 | ## Hybrid (Basic + Assembly) @@ -152,10 +177,17 @@ Happy reading!! | Title | Author | Disk Magazine | | --- | --- | --- | +| [Boot2com](sunrise_special/3/boot2com.md) | Kasper Souren | Sunrise Special 4 | | [Clock chip](future_disk/25/clock_chip.md) | ? | Future Disk 25 | +| [Copdisk](sunrise_special/4/copdisk.md) | Michel Shuqair | Sunrise Special 4 | | [Cursus DD-Graph](sunrise_special/2/cursus_dd-graph.md) | Bart Schouten | Sunrise Special 2 | | [De archeologie van de MSX](sunrise_special/3/de_archeologie_van_de_msx.md) | Bart Schouten | Sunrise Special 2 | +| [Dirsort](sunrise_special/4/dirsort.md) | Rainier Maas | Sunrise Special 4 | +| [DOS2 Batch files](sunrise_special/4/dos2_batchfiles.md) | Kasper Souren | Sunrise Special 4 | | [Get disk](sunrise_special/3/getdisk.md) | Michel Shuqair | Sunrise Special 3 | +| [Get disk 2](sunrise_special/4/getdisk_2.0.md) | Michel Shuqair | Sunrise Special 4 | +| [HD Indelen](sunrise_special/4/hd_indelen.md) | Kasper Souren | Sunrise Special 4 | +| [MBScan](sunrise_special/4/mbscan.md) | Stefan Boer | Sunrise Special 4 | | [Moonblaster Music Cursus](future_disk/18/moonblaster_music_cursus.md) | Jorrith Schaap | Future Disk 18 | | [Moonblaster Music Cursus 2](future_disk/19/moonblaster_music_cursus_2.md) | Jorrith Schaap | Future Disk 19 | | [Moonblaster Music Cursus 3](future_disk/20/moonblaster_music_cursus_3.md) | Jorrith Schaap | Future Disk 20 | @@ -163,11 +195,16 @@ Happy reading!! | [Moonblaster Music Cursus 5](future_disk/22/moonblaster_music_cursus_5.md) | Jorrith Schaap | Future Disk 22 | | [MSX-DOS 2.31](sunrise_special/2/msx-dos_2.31.md) | Kasper Souren | Sunrise Special 2 | | [MSX-DOS 2 - Redirection](sunrise_special/2/redirection.md) | Kasper Souren | Sunrise Special 2 | +| [R800 Drive](sunrise_special/4/r800_drive.md) | Kasper Souren | Sunrise Special 4 | +| [Read to kana](sunrise_special/4/read_to_kana.md) | Kasper Souren | Sunrise Special 4 | | [Rescursief programmeren](sunrise_special/1/recursief_programmeren.md) | Alex van der Wal | Sunrise Special 1 | | [Stereo SCC](sunrise_special/2/stereo_scc.md) | Haiko de Boer | Sunrise Special 2 | | [Te zachte PSG bij de NMS 8250/55/80](sunrise_special/1/te_zachte_psg_bij_de_NMS_8250_55_80.md) | Haiko de Boer | Sunrise Special 1 | | [The 2+ Corner](future_disk/15/the_2+_corner.md) | Marcel Otten | Future Disk 15 | | [Track 0 op de turbo-r](sunrise_special/1/track_0_op_de_turbo-r.md) | Stefan Boer | Sunrise Special 1 | +| [Tweede drive aan turbo-r](sunrise_special/4/tweede_drive_aan_turbor.md) | Sunrise | Sunrise Special 4 | +| [V9990](sunrise_special/4/v9990.md) | Erik Maas | Sunrise Special 4 | +| [V9990 Specificaties](sunrise_special/4/v9990_specificaties.md) | Erik Maas | Sunrise Special 4 | ## Pascal @@ -194,3 +231,9 @@ Happy reading!! | [Recursie](future_disk/21/recursie.md) | Jeroen Smael | Future Disk 21 | | [Recursie 2](future_disk/36/recursie_2.md) | Jeroen Smael | Future Disk 36 | | [Turbo Pascal Patch](sunrise_special/3/turbo_pascal_patch.md) | Pierre Gielen | Sunrise Special 3 | + + +## Handleidingen +| Title | Author | +| --- | --- | +| [MCBC 2](other/mcbc2handleiding.md) | Frank H. Druijff | diff --git a/other/mcbc2handleiding.txt b/other/mcbc2handleiding.txt new file mode 100644 index 0000000..e562d7b --- /dev/null +++ b/other/mcbc2handleiding.txt @@ -0,0 +1,772 @@ + +Inleiding + +Van harte + +Gefeliciteerd met uw aanschaf. Met MCBC zult u uw programma's nog beter (= sneller) kunnen laten werken. Leer snel met MCBC om te gaan en het programmeren ermee zal u dan spoedig veel genoegen verschaffen. + +Gemakkelijk machinetaalsnelheid + +De door u in MSX-BASIC geschreven programma's zullen door MCBC vele malen sneller gaan. Ook hoeft u niet meer allerlei zaken over de interne opbouw van de MSX-computer te kennen, die wel noodzakelijk zijn als u zelf geheel of gedeeltelijk in machinecode wilt gaan programmeren. Als u direct in Z80code programmeert zult u de MSX en zijn opbouw goed moeten kennen. Maar ook met behulp van assembly language zult u goed op de hoogte moeten zijn van vele MSXzaken. U zult echter met MCBC als gevorderd basic-programmeur vrij eenvoudig gebruik kunnen maken van de memorymapper. Hierdoor is het mogelijk in basic een programma te schrijven dat nooit in zijn geheel in het basic deel van het geheugen van uw MSX past. Ergert u zich ook altijd zo aan de mededeling na opstarten van zo'n slordige 23 duizend bytes vrij als u een machine met 128 Kbyte of zelfs 256 Kbyte heeft ? Dit hoeft nu niet meer, hak het programma in geschikte stukken en compileer de delen afzonderlijk. Zet de machinetaalcode in de verschillende delen van de memorymapper en verbindt ze met elkaar door middel van een eenvoudig basicprogramma en draaien maar. + +Handleiding + +In deze handleiding worden een aantal onderdelen onderscheiden. +Eerst wordt in het kort uitgelegd wat een compiler is en wat u er mee kunt doen. En wat veel belangrijker is wat u er niet mee kunt doen. Vervolgens zullen we wat dieper ingaan op de diverse (on)mogelijkheden van de MCBC om zo tot het hart van deze handleiding in de vorm van de gebruiksaanwijzing te komen. Dan een toelichting op de diverse demonstratie programma's. Tot slot volgt dan nog een paragraaf met technische gegevens en een lijst met problemen en mogelijke oplossing. + +Back up maken + +We raden iedereen aan om zo spoedig mogelijk een backup te maken van de geleverde schijf. U kunt MCBC zo vaak als u wilt voor persoonlijk gebruik copiëren. Doorgeven van MCBC aan derden is echter niet toegestaan. Programma's die met behulp van MCBC gemaakt werden mogen echter wel op niet commerciële basis aan derden worden verspreid. Heeft u commerciële plannen met het door u met behulp van MCBC gemaakte produkt neem dan contact met ons op voor een licentie. + +Gebruikte termen + +Mochten er voor u onbekende termen gebruikt worden kijk dan achterin de handleiding in de lijst met gebruikte termen. +In deze lijst worden alle termen in het kort verklaard, in de handleiding zelf word vaak uitgebreider op de begrippen ingegaan. +Medewerking gezocht + +Wij, van de MSX-Club, hopen dat u de resultaten niet voor zich zult houden maar als zij ook voor anderen geschikt zijn aan ons zult opsturen. Is het voor ons bruikbaar materiaal dan zullen wij het zeker helpen verspreiden en..... u kunt ook iets terug verwachten. Naast de waardering van uw mede MSX'ers kunt u ook het aanschafbedrag voor MCBC terug 'verdienen'. Als u liever iets anders wilt voor uw moeite en de club kan u daar aan helpen zal dat zeker geregeld kunnen worden. +Als redactie van het MSX Club Magazine zouden wij ook graag artikelen over het gebruik van MCBC en tips voor het gebruik willen publiceren. Bent u van plan in die geest iets te schrijven neem dan even contact op met de redactie om doublures en de daaruit volgende teleurstelling te voorkomen. +Wat is een compiler? + +Weet u al wat een compiler is en kan dan kunt u de volgende bladzijden overslaan. Weet u dat niet of weet u niet goed wat u kunt verwachten, lees dit stuk dan door omdat het u veel ergernis zal besparen bij pogingen (principieel) onmogelijke dingen van de compiler te verlangen. + +Algemeen + +Een compiler is een programma dat instructies, geschreven in een hogere programmeertaal, decodeert en een programma in machinetaal vervaardigt, dat dan op een later tijdstip kan worden uitgevoerd. + + +Een in een hogere programmeertaal geschreven programma is in principe onafhankelijk van de computer waar het programma op moet worden uitgevoerd. Sterker zelfs; het kenmerk van een hogere programmeertaal is juist dat onafhankelijk van de processor zijn. Een compiler echter wordt juist geschreven om deze hogere programmeertaal om te zetten in een code voor een bepaalde processor. Een compiler zal derhalve geschreven worden voor gebruik op een specifieke processor en in de praktijk meestal op een specifieke computer. In de rest van dit deel van het verhaal zal ik BASIC zeggen maar bijna alles zal ook opgaan voor andere hogere programmeertalen. + +Processor onderdeel computer + +Ik gebruikte hiervoor zowel het woord processor als het woord computer. Dit zijn echter verschillende begrippen al zijn beide in dit geval toepasselijk. Een processor is als het ware het hart of voor de meer pragmatischen onder u, de motor van het hele systeem. Tegenwoordig is de processor bijna altijd als ëën chip uitgevoerd die we de processor noemen. We spreken over een processing unit als hij uit meerdere componenten bestaat. Een processor zoals de Z80 die in de MSX-computer zit schrijft voor hoe de code eruit moet zien om voor hem begrijpelijk te zijn. Maar voor de processor begrijpelijk betekent nog niet automatisch voor de computer uitvoerbaar. Ook de andere componenten moeten 'meewerken' al was het maar door aanwezig te zijn. In de computer zit meer dan alleen een processor, het aanwezige geheugen speelt bijvoorbeeld een belangrijke rol. Een compiler die alleen maar BASIC omzet naar Z80-code zal dan ook lang niet alle faciliteiten die een computer biedt benutten. + +Niet alle faciliteiten + +In de praktijk van de homecomputers blijkt het meestal een illusie te menen dat een compiler alle mogelijkheden kan gebruiken die op de computer aanwezig zijn. En denk nu niet dat compilers voor andere computers dan homecomputers dit bezwaar niet kennen. Alleen ligt het daar wat anders. Op de mini's en mainframes zijn er vaak geen leuke extra's en de compiler kan dan misschien wel alle mogelijkheden benutten, maar niet doordat de compiler zo goed is, maar doordat de algemene taal in deze omgeving zo beperkt is. Zo zal ondersteuning van grafische mogelijkheden bijna altijd volledig ontbreken. De compilers die op de markt zijn gaan meestal uit van een algemeen BASIC en een algemene Z80. Een compiler kan dan snel en betrouwbaar voor eenbepaalde computer vervaardigd worden. Voor de gebruikers van zo'n compiler betekent dat echter dat juist al de leuke extra's die uw computer heeft niet gebruikt kunnen worden. En juist die extra's die uw computer onderscheidt van andere, in uw ogen mindere, machines was destijds de reden van aanschaf. Juist doordat een fabrikant zijn machine zoveel extra's heeft meegegeven, kan alleen een zeer kaal en simpel programma gecompileerd worden. + +Geheugentekort + +Voordat iemand het volgende verkeerd begrijpt, het is in het algemeen zo maar geldt juist niet voor MCBC! +Voor een volledige ondersteuning naar een code voor algemeen gebruik zijn r meestal voor homecomputers vrij veel geheugenproblemen. Een vrij simpel en klein programma dat in BASIC zo ongeveer 1 Kbyte inneemt zal in gecompileerde machinetaalcode al snel zo'n 100 of meer Kbyte groot zijn. Dit komt door een enorme overhead aan routines. De meeste compilers plaatsen bij 'onze code' voor de zekerheid alle (sub-)routines of die nu nodig zijn of niet. Dit komt voor veel computers neer op bijna de volledige inhoud van de BIOSROM's. Tevens is de opbouw van de machine in kwestie voor bijvoorbeeld het beeldscherm zodanig afwijkend dat een algemene code op processorniveau haast bij voorbaat al is uitgesloten. Vandaar dat compilers meer en meer geschreven worden niet alleen voor gebruik van het resultaat op processor maar op computer. Dit levert zoals besproken een aantal voordelen: +We kunnen als het geheugen gebruik dit toestaat de routines die in de BIOSROM's staan gebruiken zodat de gecompileerde versie veel kleiner kan zijn. +Omdat voor een speciale computer werd geschreven kan gebruikt gemaakt worden van alle hardware en software mogelijkheden van de computer. +Zeker bij homecomputers waar immers vrij veel extra's voor geluid en grafische mogelijkheden zijn opgenomen kan dit de gecompileerde code veel meer de volledige machine laten gebruiken. + +Compiler is gëën snelle interpreter + +Als u van een compiler in het algemeen onmogelijke zaken verlangt zal het resultaat een lange reeks foutmeldingen zijn en geen of een niet bruikbare code opleveren. Elke compiler eist dat u een syntactisch juiste source (broncode) levert die dan gecompileerd kan gaan worden. Zitten er in de source al fouten kan er vanzelf nooit een correcte machinecode gegenereerd worden. Pas op sommige sourcecodes lijken goed omdat zij door een interpreter wel gebruikt kunnen worden. Dit is echter geen garantie voor correct zijn van de source. Het omgekeerde is normaal wel waar : als een source niet of niet juist werkt zal een de gecompileerde versie dat ook niet doen. Het grootste gevaar schuilt echter in verschillende uitkomsten van de beide versies, de source bij de interpreter en de compiled versie daarvan, de zogenaamde object code. Beide werken op het eerste gezicht correct, maar blijken wel verschillende resultaten te geven. Wees altijd verdacht op zulke mogelijkheden. Is dit overigens zo bij een van uw programma's vertrouw dan als regel de uitslag van de object code. De syntax-controle is in dat geval veel strenger. Pas uw programmeren indien nodig aan op overzichtelijk en modulair programmeren. +Modulair programmeren + +Veel van de fouten bij programmeren met een interpreter komen vanzelf aan het licht als we streng modulair programmeren. Ik geef alvast wat voorbeelden van fouten die bij gebruik van een interpreter niet aan het licht komen en bij een compiler wel. Later in de sectie trouble shooting kom ik er nog op terug. +Bij elke lus mag altijd maar een begin en een eind zijn. +Een subroutine mag eigenlijk maar op ëën plaats verlaten worden en ook bij voorkeur maar op ëën plaats binnengegaan worden. +De verschillende onderdelen van het programma moeten in een logische opbouw op elkaar volgen. Voor veel hogere programmeertalen geldt dat de programmeur door de regels van de taal gedwongen wordt zo te programmeren. Bij BASIC is dit echter niet zo. Dit heeft voor fantasierijke programmeurs voordelen maar voor de zwakkere programmeurs betekent het vaak het produceren van spaghetti-code. Slierten zonder duidelijk begin en eind en dat lust een compiler niet. + +Fouten bij compileren + +Bij het compileren zult u vaak foutmeldingen krijgen. Er blijken twee soorten te zijn : de eerste is vrij onschuldig en u zult ze vaak tegenkomen; u maakte een typefout, vergat een haakje, zette er een teveel of iets dergelijks. Elke compiler zal u op deze fout wijzen en na de verbetering van de fout is het probleem weg. De andere fout is lastiger. Er kan niet gecompileerd worden omdat de compiler de structuur van uw programma niet begrijpt. Zoek de fout dan het eerst bij het niet voldoende modulair opzetten van het programma. + +Fouten na compilatie + +Ook na compilatie blijken sommige programma nog steeds niet correct te werken. Als de normale versie voor compilatie nog wel werkte zal vrijwel altijd de fout gevonden kunnen worden in de structuur van het programma. Op het opsporen van deze fouten kom ik later nog terug. +De compiler MCBC + +Bij het schrijven van MCBC waren er de volgende uitgangspunten. + +Als allerbelangrijkste: + +De bedoeling is het om programma's te schrijven in MSX-BASIC en dan met vrijwel machinetaal tempo op de MSX te laten draaien. + +Als hoofduitgangspunten: + + De compiler zelf mag geen geheugenruimte in beslag nemen die door BASIC kan worden gebruikt. + De object code die na complatie verkregen wordt mag geen geheugenruimte in beslag nemen die door BASIC kan worden gebruikt. + De runtime versie moet zonder compiler of andere software hulpmiddelen kunnen werken. + +Als direct gevolg van het eerste van de voorafgaande punten: + + De compiler zelf moet in een memorypage passen en zal dientengevolge maximaal 16 Kbyte groot mogen zijn. + +Verder hield Adriaan rekening met: + + De compiler zelf moet in elke MSX-2 met memorymapper gebruikt kunnen worden. + De object code dient klein en snel te zijn. +Om een hoge snelheid te halen wordt geen runtime errorhandling ingebouwd. MCBC gaat er van uit dat de te compileren source correct is. Goede (of luie) programmeurs kunnen hier soms slim gebruik van maken. + Wordt in de source een fout gevonden zal de fout gemeld worden en de compilering wordt gestaakt. + Vooral de grafische kant van de MSX-computer, vooral MSX-2, moest ondersteund worden. + In verband met de keuze voor snelheid en grafische zaken is gekozen voor alleen integers als getallen. + +En tot slot moest gelden: + + De normale goede BASIC-programmeur moet zonder veel rompslomp gebruik kunnen maken van MCBC. + + +Opzet MCBC + +In het geval van MCBC is de hogere programmeertaal een deel van de MSX-BASIC en de gegenereerde machinetaalcode een code voor de Z80 processor die toegang moet hebben tot de zogenaamde BIOS-routines in de ROM's van de MSX computer. Dit laatste lijkt een behoorlijke beperking, maar is in feite niets anders dan een slim gebruik maken van de inhoud van de ROM's in de MSX-computer. Wilt u de door MCBC gegenereerde object code op een andere computer met Z80-processor laten werken dient u de inhoud van de BIOS voor een deel mee te nemen. Na deze waarschuwing hierover zal ik er niet verder op ingaan omdat het niet in de opzet van de compiler ligt om algemene Z80 code te maken. +De object code kan vanzelfsprekend op een duurzaam medium, zoalsdiskette, worden weggeschreven. Als het programma later gebruikt moet gaan worden, zal u het moeten laden op de juiste plaats in het geheugen en dan starten. Bij deze beide onderdelen moet u enige kennis hebben van de geheugenopbouw en geheugengebruik van uw MSX-computer. De compiler of beter gezegd het hulpprogramma CONTROL kan u meestal een aantal van de benodigde gegevens verschaffen. Ook deze handleiding zal vermoedelijk voor normaal gebruik voldoende informatie kunnen verschaffen om MCBC te kunnen gebruiken. + +Beperkingen + +Er wordt een machinetaalprogramma door MCBC vervaardigd dat slechts in bepaalde delen van het geheugen van de MSX-computer kan werken. Dit zijn niet de delen van het geheugen die door uw BASIC-programma worden gebruikt. +MCBC gaat uit van een correcte source, zijn er fouten zoals 'PLINT' in plaats van 'PRINT' zal de compilatieslag eindigen met een normale foutmelding. Worden getallen bij berekeningen tijdens de werking van het programma echter te groot zodat we bij de interpreter een 'Overflow in rnr' foutmelding krijgen, zal het object code programma gewoon doorgaan. +Een object code zal zonder maatregelen van te voren NIET te onderbreken zijn. +Niet de volledige MSX-BASIC wordt ondersteund wat wel ondersteund wordt leest u in de volgende paragraaf. +Ondersteuning in de Msx Club Basic Compiler : + +Bij geen enkele compiler zal ooit de volledige MSX-BASIC gecompileerd kunnen worden omdat een aantal van de instructies direct betrekking heeft op de normale interpreter verwerking van MSX-BASIC. Ook zijn er instructies die niet zinvol gecompileerd kunnen worden. RENUM en LIST zijn, om een tweetal voorbeelden te noemen, vrij onzinnige instructies in een gecompileerde code. Er kan niets meer gelist worden omdat de BASIC nu is omgezet in Z80-code en omdat daarmee ook de regelnummers, sterker, zelfs de regels verdwenen, kan ook bezwaarlijk worden hernummerd. +Een lijst van de wel te gebruiken BASIC-statements, rekentekens en variabelentypes staat in de volgende paragraaf. + +Ondersteund worden : + +variabelen van het type integer (!) +dat zijn gehele getallen zonder breukdeel, dus geen cijfers achter de decimale komma/punt. De grootte ligt tussen minimum -32768 en maximum 32767. + +variabelen van het type string ($) +dat zijn teksten. Zij kunnen wel getallen voorstellen, maar die worden dan nu als tekst met cijfers opgevat. + +Eën dimensionale arrays zowel van tekst als integertype + +De rekentekens + +g voor groter dan += voor gelijk aan +k voor kleiner dan + +en de combinaties hiervan g=, k=, kg + +Pas op! +De in feite overbodige mogelijkheden =g, =k en gk kunnen niet gebruikt worden. + ++ voor optellen +- voor aftrekken +* voor vermenigvuldigen +\ voor delen.................PAS OP! + Dit bent u waarschijnlijk niet gewend. + en * heeft hogere prioriteit dan \ +- om het tegengestelde van een waarde te krijgen. + +Nu volgt een lijst met de BASICstatements die gebruikt kunnen worden en in het kort waar ze voor dienen. In deze lijst staan x en y voor een of andere getalwaarde gebruikt die u zelf als getalconstante dient in te vullen. a,b, enz. voor een variabele die u zelf met naam kunt aangeven. Natuurlijk kunnen in dit geval ook constanten of expressies gebruikt worden. Met t$ geef ik een tekstvariabele aan die overigens altijd ook als constante kan worden opgegeven. Voor een regelnummer wordt de term rnr gebruikt. Voor de duidelijkheid nog even dit : staan in lijst x en of y genoemd betekent dat dat er geen variabele of expressie mag worden ingevuld. Het is echter niet de bedoeling dat ik hier een complete syntax beschrijving van de diverse BASICstatements ga geven. Bij voorbaat verontschuldig ik mij voor in deze lijstgemaakte fouten en onduidelijkheden. Ik moet te zeer in detail gaan om alles perfect te vertellen. Ik verwijs daarom voor de juiste syntax naar de handboeken. Mochten er problemen zijn probeer deze dan te isoleren en als zij opgelost zijn laat het anderen door middel van ons magazine weten. Lukt het niet de problemen op te lossen vraag dan via het blad om hulp. + +ABS(a) | om de absolute waarde van a te bepalen. + +a AND b | om een logische 'and' van a en b te doen + +ASC(t$) | om de ASCII waarde van het eerste teken van een tekstvariabele t$ te bepalen. + +CHR$(a) | Om tekstvariabele met ASCII-code a te krijgen. + +'''CLEAR x | Om geheugendeel te reserveren. Er kan mee worden ingesteld hoeveel geheugen voor stringhandling wordt gebruikt. Maakt geen geheugen vrij voor machinecode daar tweede parameter niet wordt gebruikt. Maakt niets schoon, wist niets, sluit geen bestanden en zal ook niets zoals DEFINT of DEF FN herzetten! + +CLS | Om het scherm schoon te maken. + +COLOR a,b,c | Om kleurenset te kiezen en/of in te stellen. Zonder vermelden van kleur werkt dit als COLOR=NEW. + +COLOR=NEW | Om de kleuren weer volgens de defaultwaarden te krijgen. + +COLOR=RESTORE | Om de kleurenset te herstellen volgens de eerder opgeslagen gegevens. + +COLOR SPRITE(a) | Om de kleur van de sprite te geven. + +COLOR SPRITE$(a) | Om de kleur van de sprite per lijn te geven. + +'''COPY (a,b)-(c,d) TO (e,f) | Om grafische schermdelen (mag gehele scherm zijn) te copiëren naar andere delen van dezelfde schermpagina of van andere schermpagina's. In syntax kan ook nog schermpagina en indien gewenst een logische operator opgegeven worden. + +DEFDBL | Om aan te geven dat bepaalde variabelen van het double precision type zijn. Achter DEFDBL de beginletters van de variabelen vermelden. +Alleen te gebruiken om ruimte te reserveren. Voorbereiding op eventuele uitbreiding MCBC. + +DEFINT | Om aan te geven dat bepaalde variabelen van het integertype zijn. Achter DEFINT de beginletters van de variabelen vermelden. +Voor MCBC nodig maar wel verplicht opnemen of immer een % achter de naam van de variabele. + +DEFSNG | Om aan te geven dat bepaalde variabelen van het single precision type zijn. Achter DEFSNG de beginletters van de variabelen vermelden. +Alleen te gebruiken om ruimte te reserveren. Voorbereiding op eventuele uitbreiding MCBC. +DEFSTR | Om aan te geven dat bepaalde variabelen van het string (=tekst) type zijn. Achter DEFSTR de beginletters van de variabelen vermelden. + +'''DIM a(x) | Om de grootte van de array's die gebruikt gaan worden aan te geven. Er kan niet opnieuw worden gedimensioneerd. Moet met getalwaarde, dus constante, opgegeven worden. + +ELSE | Om alternatief te geven. Alleen in de combinatie met IF...THEN.... en de combinatie IF...GOTO.... te gebruiken. + +a EQV b | Om een logische 'eqv' met a en b te doen. + +FIX(a) | Om het geheeltallige deel van een variabele te krijgen. Identiek aan INT voor niet negatieve getallen. Voorbereiding op eventuele uitbreiding MCBC. + +FOR | Om een programmalus te maken. Alleen te gebruiken in de combinatie FOR a=x TO y in dezelfde regel en NEXT verderop in het programma. + +GOSUB rnr | Om naar de subroutine met het opgegeven regelnummer te gaan. + +GOTO rnr | Om naar een andere plaats met het opgegeven regelnummer in het programma te gaan. + +IF | Om een conditie te testen. Alleen te gebruiken in de combinatie IF...THEN... of IF...GOTO.... + +a IMP b | Om een logische 'imp' met a en b te doen. + +INKEY$ | Om het toetsenbord te scannen. + +INP(a) | Om een byte van de aangegeven poort te lezen. + +INT(a) | Kapt het breukdeel van variabele er af. Door de notatie worden negatieve getallen 1 kleiner dan verwacht. Voorbereiding op eventuele uitbreiding MCBC. + +KEY (a) ON | Om direct na indrukken functietoets ergens heen te springen. +Alleen te gebruiken in combinatie met ON KEY ... die voor deze instructie ergens in het programma opgenomen moet zijn. + N.B. | Niet om de inhoud van de functietoetsen op scherm te zetten. De (a) is dan ook verplicht. + +KEY (a) OFF | Om niet meer direct na indrukken functietoets ergens heen te springen. +Alleen te gebruiken in combinatie met ON KEY ... en KEY ON die voor deze instructie ergens in het programma opgenomen moet zijn. + N.B. | Niet om de inhoud van de functietoetsen van scherm te halen. De (a) is ook verplicht. + +KEY (a) STOP | Om niet meer direct na indrukken functie toets ergens heen te springen maar wel om bij te houden of de toets ingedrukt wordt. +Alleen te gebruiken in combinatie met ON KEY ... en KEY ON die voor deze instructie ergens in het programma opgenomen moet zijn. +LEFT$(t$,a) | Om het linkerdeel van a tekens lengte van de tekstvariabele t$ te pakken. + +LEN(t$) | Om de lengte van een tekstvariabele t$ te krijgen. + +LET | Om voor een toewijzing te zetten. Niet verplicht om te gebruiken. + +LINE (a,b)-(c,d),k | Om een lijn te tekenen. De syntax is veel uitgebreider maar daar ga ik nu hier niet verder op in. + +LINE (a,b)-(c,d),k,B | Om een kader te tekenen. De syntax is veel uitgebreider maar daar ga ik nu hier niet verder op in. + +LINE (a,b)-(c,d),k,BF| Om een blok te tekenen. De syntax is veel uitgebreider maar daar ga ik nu hier niet verder op in. + +'''MID$(t$,a,b) | Om een deel vanaf positie a met lengte b uit het midden van een tekstvariabele t$ te krijgen. + N.B. De functie MID$ wordt niet ondersteund. + +a MOD b | Om de rekenkundige a modulo b bewerking te doen. + +NEXT | Om het einde van een programmalus aan te geven. + +NEXT i,j | Om het einde van de programmalus(sen) met index i (,j enz.) aan te geven. + +NEW | Om in combinatie met COLOR de kleuren in de default waarde te zetten. +N.B. : werkt niet om programma te verwijderen. + +NOT a | Om een logische 'not' met a te doen. + +ON...GOTO rnr,rnr | Om afhankelijk van de waarde na ON naar de regel met het opgegeven regelnummer te springen. + +ON...GOSUB rnr,rnr | Om afhankelijk van de waarde na ON naar de subroutine met het opgegeven regelnummer te springen. + +ON INTERVAL GOSUB rnr | Om na verstrijken van een bepaald interval naar de subroutine met het opgegeven regelnummer te springen. Alleen te gebruiken in combinatie met INTERVALON. + +ON KEY GOSUB rnr,rnr | Om na indrukken functietoets naar de subroutine met het opgegeven regelnummer te springen. Alleen te gebruiken in combinatie met KEY (a) ON. + +ON SPRITE GOSUB rnr | Om bij de botsing van twee sprites naar de subroutine met het opgegeven regelnummer te springen. Alleen te gebruiken in combinatie met SPRITEON. + +ON STOP GOSUB rnr | Om bij indrukken van de [CTRL] & [STOP] combinatie naar de subroutine met het opgegeven regelnummer te springen. + +ON STRIG GOSUB rnr | Om bij indrukken van de actieknop van muis of joystick naar de subroutine met het opgegeven regelnummer te springen. Alleen te gebruiken in combinatie met STRINGON. +a OR b | Om een logische 'or' met a en b te doen. + +OUT a,b | Om een waarde b naar de opgegeven poort a te zenden. Lijkt in syntax en opzet sterk op POKE. + +PAD(a) | Om de paddle uit te lezen. + +PAINT (a,b),c,d | Om een willekeurig vlak in te kleuren. + +PDL(a) | Om de stand van de joystick uit te lezen. + +PEEK (a) | Om de inhoud van een geheugenadres (ëën byte) te lezen. Houd rekening met geheugenpagina's. Voor de adressen tussen &H4000 en &H8000 mag u er vrij zeker van zijn andere waarden te krijgen, uitzonderingen daargelaten. + +POINT (a,b) | Om de kleur van een beeldpunt te lezen. + +POKE a,b | Om de inhoud van een geheugenadres (ëën byte) te schrijven. Voor de adressen tussen &H4000 en &H8000 geldt nu dat het RAMgeheugen is en niet zoals normaal ROMgeheugen. Er valt nu dus wel in te POKE'n. + +PRESET (a,b) | Om een punt in de achtergrondkleur te tekenen. De syntax is veel uitgebreider maar daar ga ik nu hier niet verder op in. + +PRINT | Om een variabele of constante op het scherm te zetten. De syntax is veel uitgebreider maar daar ga ik nu hier niet verder op in. Pas op USING kan niet gebruikt worden. + +PSET (a,b) | Om een punt in de voorgrondkleur te tekenen. De syntax is veel uitgebreider maar daar ga ik nu hier niet verder op in. + +PUT SPRITE a,(b,c) : Om een sprite a op het scherm a in de voorgrondkleur te plaatsen. De syntax is veel uitgebreider maar daar ga ik nu hier niet verder op in. + +REM | Om opmerkingen in de listing te maken. Wordt niet vertaald en u kunt er dus net zoveel commentaar in zetten als u wilt. Ook ' kan gebruikt worden. + +RESTORE | Om de kleurenset te herstellen volgens de eerder opgeslagen gegevens in de combinatie COLOR=RESTORE. Werkt niet om de READpointer op een andere plaats te zetten. + +RETURN | Om aan het eind van een subroutine terug te keren naar het punt waar vandaan naar de subroutine werd gesprongen. + +RETURN rnr | Om te gaan naar het gewenste adres. Het verschil met GOTO is dat nu de stack van de returnadressen ëën wordt verlaagd. +Vaak nodig na een onderbreking door een ON....GOSUB...routine. + +RIGHT$(t$,a) | Om het rechterdeel van a tekens lengte van de tekstvariabele t$ te pakken. + +SCREEN a,b | Om het gewenste scherm te kiezen en een aantal andere instellingen te doen. Zonder parameters werkt het als eenCLS. De syntax is veel uitgebreider maar daar ga ik nu hier niet verder op in. + +SET PAGE a,b | Om grafische schermpagina te kiezen voor zichtbare of onzichtbare status, respectievelijk actieve of passieve status. + +SGN(a) | Om het teken van een variabele te krijgen. + +SOUND a,b | Om een waarde b in geluidsregister a te plaatsen. +Als meerdere geluidsregisters met de juiste waarden gevuld zijn kan zo een geluid gemaakt worden. Vergelijkbaar met POKE en OUT. + +SPRITE OFF | Om de spritebotsingen detectie uit te zetten. + +SPRITE ON | Om de spritebotsingen detectie aan te zetten. + +SPRITE STOP | Om de reactie op spritebotsingen uit te zetten. + +SPRITE$(a) | Om een sprite in de spritetabel te plaatsen. + +STEP | Om bij grafische instructie de locatie relatief ten opzichte van laatst behandelde punt te nemen. + +STEP a | Om de stapgrootte bij een programmalus aan te geven. Alleen in combinatie met FOR...TO... NEXT + +STICK(a) | Om de status van cursor of joystick te lezen. + +STRIG(a) | Om de status van actieknoppen (op een joystick of de spatiebalk) te lezen. + +STRIG (a) OFF | Om STRIG (a) ON effect weer af te zetten. Kan dus alleen in combinatie met STRIG ON en ON STRIG GOSUB rnr gebruikt worden. + +STRIG (a) ON | Om na iedere instructie de status van de actieknop te lezen. En indien er actie gevraagd wordt te springen naar de subroutine. Kan alleen in combinatie met ON STRIG GOSUB rnr gebruikt worden. + +STRIG (a) STOP | Om na iedere instructie de status van de actieknop te lezen, maar niet naar de subroutine te springen. Kan alleen in combinatie met STRIG ON gebruikt worden. + +STR$(a) | Om de numerieke waarde a als tekststring te krijgen. Denk eraan dat nietnegatieve waarden beginnen met een spatie! + +THEN | Om gevolg van actie mee te beginnen. Kan alleen in de combinatie met IF...THEN... gebruikt worden. + +TIME | Om de interne teller (een systeemvariabele) te lezen of te schrijven. + +TO | Om de eindgrens bij een programmalus aan te geven. Kan alleen in de combinatie met FOR...TO... in zelfde regel en NEXT gebruikt worden. + +USR(a) | Om een machinetaalroutine aan te roepen. Kan alleengebruikt worden als de DEF USR a al gedefinieerd is. Dit kan echter NIET in het te compileren deel staan maar dient voor de aanroep van de object code te geschieden. + +VARPTR(a) | Om de plaats waar een variabele in het geheugen staat te weten te komen. + +VDP(a) | Om het betreffende VDP-register te lezen of te schrijven. + +VPEEK (a,b) | Om een geheugenplaats (byte) in het videoRAM te lezen. + +VPOKE a,b | Om een geheugenplaats (byte) in het videoRAM te schrijven. + +a XOR b | Om een logische 'xor' met a en b te doen. + +' | Te gebruiken als REMstatement. Dubbele punt is er niet voor nodig. Wordt niet opgenomen in de object code. + +NIET ondersteund + +Floating point variabelen + +Meer dimensionale arrays + +ATN | BASE | BEEP | BIN$ | CIRCLE | CLOSE | COS | CSRLIN | DATA | DRAW | DSKF | DSKI$ | DSKO$ | EOF | ERASE | EXP | FIELD | FN | FPOS | GET | HEX$ | INPUT | INSTR | LOC | LOCATE | LOF | LOG | LSET | OPEN | PLAY | POS | READ | RESUME | RND | RSET | SIN | SPACE$ | SPC | SQR | STRING$ | TAB | TAN | USING | VAL | WIDTH + + +NIET zinnig om te ondersteunen + + +ATTR$ | AUTO | BLOAD | BSAVE | CALL | CDBL | CINT | 'CLEAR' | CLOAD | CMD | CONT | CSAVE | CSNG | CVD | CVI | CVS | DELETE | END | ERL | ERR | ERROR | FILES | FRE | IPL | KILL | LFILES | LIST | LLIST | LPOS | LPRINT | LOAD | MAXFILES | MERGE | MKD$ | MKI$ | MKS$ | MOTOR | NAME | OCT$ | RESTORE | RENUM | RUN | SAVE | SWAP | TROFF | TRON | + +De rekentekens / ^ + +Het is duidelijk dat als de compiler geschikt gemaakt zou worden voor gebruik met floating point getallen een aantal statements die nu bij 'niet zinnig' staan dan bij 'niet ondersteund' komen. Sommige statements worden in de lijst met ondersteunde statements genoemd na aanhalingstekens. Dit is om aan te geven dat de compiler niet op alle punten de toegestane syntax kan volgen. In sommige gevallen is dit zeer duidelijk DIM werkt nu alleen voor eendimensionale arrays, maar in andere gevallen is er sprake van een soms te betreuren beperking, MID$ kan alleen gebruikt worden als een soort LEFT$ of RIGHT$ dus als functie maar niet als opdracht. Bij de niet volledig te gebruiken statements staan steeds de beperkingen genoemd. Experimenteer echter gerust het kan zijn dat in de laatste versie van MCBC juist de beperking die u wilde gebruiken is opgeheven. Lees daarover steeds ons magazinewaar regelmatig tips in zullen komen om met MCBC te werken. + +Geheugengebruik. + +Bij MCBC kan de programmeur het gehele geheugen dat normaal gebruikt kan worden nog steeds gebruiken. Sterker nog; de gecompileerde delen staan in andere pagina's en het oorspronkelijke BASIC programma zou zelfs wel een 80 Kbyte of meer groot kunnen zijn. Van dit programma zijn dan een aantal delen gecompileerd zodat het resterende basic programma wel in de machine (in het normale basic geheugendeel) past. De compiler zelf neemt tijdens werking gëën basic geheugen in beslag. Een basic programma dat dus met alleen ondersteunde statements geprogrammeerd is en meer dan 20 Kbyte groot is kan verwerkt worden in ëën compileslag, mits de resulterende code niet boven de 32 Kbyte komt. Het is met MCBC ook voor de eenvoudige basicprogrammeur mogelijk het gehele geheugen van de MSX-2 (tot 4 Mbyte indien aanwezig in uw computer) te gebruiken. + +Een te compileren programma zal zowel groter als kleiner kunnen worden in de gecompileerde versie. Om informatie hierover te krijgen moet in CONTROL optie 3 gekozen worden. + +Snelheidswinst + +De snelheidswinst is sterk afhankelijk van de gebruikte instructies. Bij PAINT is bijvoorbeeld vrijwel geen winst te verwachten. Ook zullen alle SCREEN 2 acties nauwelijks (of niet) sneller verlopen. In bepaalde gevallen kan de snelheidswinst wel 2000 % of meer bedragen. Vooral de spritebewegingen winnen enorm aan snelheid. Ik heb de standaard benchmarks aangepast op werken met integers en geef hier de tijden van de basic versie versus de gecompileerde versie. + +Benchmark #1 voor .95 sec na .06 sec dat is 16 x sneller +Benchmark #2 voor 3.98 sec na .06 sec dat is 62 x sneller Ja, echt waar tweemaal gecontroleerd ! + +Benchmark #3 voor 19.08 sec na 1.42 sec dat is 13 x sneller +Benchmark #4 voor 17.98 sec na 1.36 sec dat is 13 x sneller +Benchmark #5 voor 10.18 sec na 1.38 sec dat is 7 x sneller +Benchmark #6 voor 17.76 sec na 1.74 sec dat is 10 x sneller +Benchmark #7 voor 29.66 sec na 1.88 sec dat is 16 x sneller + +We zien dus een enorm verschil tussen de verschillende benchmarks. Overigens kon benchmark #8 niet gedraaid worden wegens uitdrukkelijk gebruik van floating point getallen. De tijden vóór zijn NIET van de standaard benchmarks maar de aangepaste integerversies ervan. Het is natuurlijk erg oneerlijk een floating point basic programma te gaan vergelijken met een integer machinetaal routine. Op de diskette staan al deze benchmark programma's zodat u het zelf ook nog eens kunt nagaan. + +Resetbestendig + +Zowel de MCBC als de gegenereerde code zijn reset bestendig. Het is trouwens erg grappig om te zien dat dat met een BASIC programma, waarin een _MEM naar een gecompileerde code staat, rustig aangepast kan worden (de sprites worden bijvoorbeeld anders gevuld) en dan zonder verdere ingrepen weer loopt. Als weeven nadenken is dat logisch, als een programma de spritebeweging in een subroutine regelt is het te verwachten dat als de sprites in een ander deel van het programma anders gevuld worden, de subroutine in kwestie nog steeds eender werkt. + +Interrupts + +Een werkende object code kan niet onderbroken worden zonder speciale maatregelen. U kunt zelf een stop inbouwen, bijvoorbeeld toetsenbord regelmatig scannen of een tijdsinterrupt. Anders voor aanroep van object code een POKE &HFBB0,1 om er voor te zorgen dat met het gelijktijdig indrukken van [SHIFT] & [CODE] & [GRAPH] & [CTRL] de werking kan onderbroken worden. +Pas op 1 : deze optie werkt pas nadat de toetsenbordscan weer aangezet is. U kunt daarvoor zorgen door in het begin van het programma een BIOScall te doen, bijvoorbeeld door CLS. +Pas op 2 : Deze onderbreking van het programma is een zogenaamde warme restart, de machine staat nog steeds in het gebruikte, dus vaak grafische, scherm. U dient na de onderbreking zelf (vaak blind) SCREEN 0 in te typen en eventueel kleur in te stellen voordat u iets kunt lezen. Het voorafgaande zal u vermoedelijk doen besluiten maar een onderbreking naar eigen maaksel te verzorgen. + +Werken met MCBC in de praktijk + +Hoe werken we met MCBC ? Wij bekijken hiervoor twee mogelijkheden die enigszins anders behandeld dienen te worden. Ten eerste is er de mogelijkheid dat u nu u weet wat de mogelijkheden zijn van MCBC een programma schrijft dat volledig rekening houdt met de mogelijkheden en beperkingen van MCBC. Ook kan het natuurlijk zo zijn dat ëën van uw programma's toevallig al geheel uit toegestane statements bestaat. In dit geval kunnen we de gehele source compileren. +Ten tweede is er de mogelijkheid dat we een bestaand basic programma hebben dat we graag gedeeltelijk willen compileren in verband met de snelheid. Alles compileren zou misschien wel leuk zijn, maar zal bijna nooit kunnen omdat er niet ondersteunde statements in het programma voorkomen. Aangezien deze laatste mogelijkheid de moeilijkste is en ook vrij vaak zal voorkomen in de praktijk begin ik met het bespreken van dit geval. + +Let op de extensies + +In de volgende verhandeling ga ik er van uit dat u dezelfde extensies gebruikt als ik. Aangezien het gehele verhaal nogal complex kan worden door het vrij grote aantal files dat in het verloop van de verhandeling een rol gaat spelen is het van vrij groot belang dat we er streng op toezien de juiste extensie te gebruiken. De afspraken voor de extensies berusten op logische gronden en zijn daarom redelijk simpel te onthouden. We gaan uit van een normaal BASICprogramma dat dan ook de extensie .BAS heeft. Dit programma passen we zodanig aan dat het gecompileerd kan worden. Het programma dat we nu krijgen geven we de extensie .B2M. De extensie .B2M is een soort acroniem voor Basic to (2=two) Memory, zodat we aan de extensie kunnen zien dat dit een programma(deel) is dat gecompileerd kan gaan worden. Is de .B2Mfile eenmaal gecompileerd wordt die weggeschreven onder de extensie .MEM een afkorting voor memory. Om het programma in gecompileerde vorm te laten werken is er natuurlijk nog eenloader nodig die alles op de juiste plaats in het geheugen zet. Deze loader heeft zoals gebruikelijk de extensie .LDR. Tot slot hebben we nog het BASICprogrammadeel dat de gecompileerde versie aanroept en eventueel de niet ondersteunde zaken regelt. Omdat dit programma altijd met de .MEM wordt gebruikt is de gekozen extensie .B4M dat staat voor Basic for (4=four) Memory. Door de gekozen .B2M en .B4M is het duidelijk dat ook aan .B1M en .B3M betekenissen zijn gegeven. Deze twee files zijn echter niet altijd nodig. Onder de .B1Mfile versta ik de file die bewerkt is om gesplitst te kunnen worden in ëën te compileren en ëën niet te compileren deel. Deze .B1Mfile kan in principe gelijk zijn aan de .BASfile maar zoals u in het gebruik van MCBC zult leren zullen er wel verschillen zijn. Ik om hier later nog op terug. De .B1Mfile wordt gesplitst in een .B2Mfile die gecompileerd gaat worden tot .MEMfile en een .B3Mfile die het niet te compileren deel bevat. Deze .B3Mfile wordt minimaal met een _MEM aangevuld tot de .B4Mfile. Als u wilt en kunt is het mogelijk om de lader .LDR en het aanroepprogramma .B4M te combineren. Ik zou hiervoor dan toch de extensie .LDR gebruiken maar ook .RUN is een redelijke keus. Lees eerst de volgende tekst door en kijk dan nog eens naar deze uitleg van de extensienamen en naar het korte overzicht dat verderop nog eens gegeven wordt. + +Programma bevat niet ondersteunde statements + +In dit eerste geval moeten we de volgende stappen ondernemen: + +Begin met een nieuwe schijf en zet daar MCBC.BIN en het programma CONTROL en eventueel LOADER.BAS op en verder het programma dat u wilt gaan compileren. + +Neem het basicprogramma (ik geef dat van nu af aan met .BAS aan) door op het deel dat te compileren is. Is dit deel er niet of nauwelijks en het moet toch met MCBC versneld worden dan zal het programma zodanig aangepast moeten worden dat een deel in toegestane statements staat en alleen integers gebruikt. Het zal in vele gevallen blijken dat een beetje bewuster programmeren het programma al zonder compileren aanzienlijk versnelt. + +Aanpassen op compilatiemogelijkheid + +Om het programma zo goed mogelijk aan te passen voor compilatie zoeken we eerst alle zeer beslist niet te compileren delen. Kies zoveel mogelijk ondersteunde statements ook in de stukken die toch niet gecompileerd kunnen worden. Als MCBC wordt uitgebreid is uw programma al beter voorbereid. Schrijf bepaalde stukken misschien over. Als ik bij voorbeeld een klein array van zo'n 12 waarden moet vullen zal ik bijna altijd kiezen voor de oplossing: + FOR I=1 TO 12 + READ A(I) + NEXT + DATA 2,2,3,4,4,5,6,6,7,8,8,9 +Maar nu is het misschien het overwegen waard om daar maar eens het volgende van te maken: + A(1)=2:A(2)=2:A(3)=3:A(4)=4:A(5)=4:A(6)=5 + A(7)=6:A(8)=6:A(9)=7:A(10)=8:A(11)=8:A(12)=9 +Veel van de variabelen blijken best integer te kunnen zijn en al voor compilatie worden we zo vaak verrast met een sneller programma. Dan zorgen we ervoor dat de niet te compileren stukkennetjes bij elkaar staan. En om goed duidelijk te maken welk deel wel gecompileerd kan gaan worden is het een goed idee dat deel in een subroutine aan het eind van het programma te plaatsen. Op de oorspronkelijke plaats komt dan een GOSUB rnr te staan. Vooruitlopend kan ik nu reeds zeggen dat aan het eind van al onze operaties een _MEM op de plaats van de GOSUB rnr komt te staan. Vervolgens gaan we de communicatie tussen de beide programmadelen verzorgen. + +Uitwisselen van variabelen + +Een normale subroutine gebruikt automatisch dezelfde variabelen als het hoofdprogramma. Maar de communicatie tussen het basic deel (.B4M) en de machinetaalroutine (.MEM) zal anders moeten geschieden. Vergelijk in basic een programma A dat eindigt met RUN "B" en B eindigt met RUN "A". Ook in dat geval zullen alle waarden van variabelen tijdens laden van het andere programma verloren gaan. We moeten de variabelen van het ene basicdeel aan het andere machinetaaldeel doorgeven. En aan het eind weer teruggeven voorzover dat nodig is. We kunnen dit doen door vlak voor de _MEM een aantal POKE's te doen. Weten we bijvoorbeeld dat de geheugenadressen vanaf 9000 vrij zijn kunnen we de variabele A als volgt doorgeven : + +In het resterende basicdeel, dat na de splitsing .B3M en later .B4M moet worden zetten we : + +xxx POKE &H9000,A MOD 256:POKE &H9001,A\256 + +In het te compileren deel (nu nog subroutine maar straks .B2M) nemen we op : + +yyy A=PEEK(&H9000)+256*PEEK(&H9001) + +Moet de waarde van A weer terug gegeven worden dan moet in het te compileren deel ook de regel xxx staan en na terugkomst in het resterende basicdeel ook regel yyy. +Weten we echter zeker dat de waarde van A nooit meer dan 255 zal bedragen (voor schermcoördinaten is dit vrij waarschijnlijk) dan kan het eenvoudiger met + +xxx POKE &H9000,A + +en later + +yyy A=PEEK(&H9000). + +Om te voorkomen dat lange reeksen POKE's en PEEK's ingetoetst moeten worden kunnen we ook meerdere variabelen met een string doorgeven. We slaan de variabelen op in een tekststring b.v. : + +T$=CHR$(A)+CHR$(B)+CHR$(F)+.....+CHR$(M) + +en dan kan met + +POKE &H9000,VARPTR(T$) MOD 256 en +POKE &H9001,VARPTR(T$)\256 + +het adres van T$ doorgegeven worden. En door wat PEEK's (op 9000 en 9001) vinden we T$ en zo de variabelen weer terug. Veilige adressen om te POKE'n zijn meestal de adressen in het videogeheugen. Hiervoor dan natuurlijk wel VPEEK en VPOKE gebruiken. Eventueel in een niet-gebruikte pagina. En bedenk dat ook het machinetaaldeel ze moet kunnen vinden, ga het dus niet in een pagina zetten die straks wordt uitgeschakeld. Probeer het uitwisselen van variabelen echter tot een minimum te beperken, het kan de werking van het eindresultaat negatief beïnvloeden. Het vervelende is dat we zolang we met de interpreter werken natuurlijk alle variabelen worden doorgegeven aan de subroutine. Wilt u er echt zeker van zijn dat alles correct werkt dan kunt u zoals al eerder werd gemeld het programma scheiden in twee aparte programma's. Het ene programma laadt dan het andere en omgekeerd. Alle variabelen worden dan echter steeds bij elke nieuwe run op nul gezet en als het doorgeven met PEEK en POKE respectievelijk VPEEK en VPOKE niet goed is gedaan ziet u dat snel aan het resultaat. + +Laatste stappen voor splitsen + +Ook zal in het te compileren deel de instructie DEFINT AZ opgenomen dienen te worden en met een DIM aangegeven moeten worden hoe groot de arrays zijn. Maar nu werkt het niet meer correct in een ongesplitst basicprogramma !!!! We krijgen 'Redimensioned array in rnr' als foutmelding. We moeten dit dus pas als allerlaatste vlak voor compileren er tussen voegen. De bewerkte .BAS die nog net loopt in BASIC geven we aan met de extensie .B1M. Deze naamgeving wordt verderop duidelijker. De .B1Mfile wordt op schijf weggeschreven, niet voor de aardigheid maar om te voorkomen dat u straks alles weer opnieuw moet doen! Nu wordt naar keuze het te compileren of het resterende deel gewist met DELETE rnrrnr. Ik raad aan te beginnen met het te compileren deel, enerzijds omdat we dan snel na een compilatiepoging zien dat er nog iets aan het andere deel veranderd moet worden en anderzijds omdat de naamgeving al aanleiding geeft eerst .B2M en dam pas .B3M te behandelen. Het deel dat gecompileerd gaat worden wordt zonodig aangevuld met de DIM en de extra DEFINT A-Z. Als het inderdaad zoals aanbevolen een subroutine is moet de return in de laatste regel (!!!) vervangen worden door bijvoorbeeld REM EINDE. Vervolgens wordt deze versie op schijf gezet met de extensie .B2M. De extensie .B2M staat voor Basic to (2=two) Memory. Het andere deel (.B1M min .B2M) dat basic blijft gaat naar schijf met de extensie .B3M. Om dit voorelkaar te krijgen laden we eerst de .B1M en verwijderen daaruit de .B2M met DELETE rnrrnr en houden dan vanzelf .B3M over. + +Compileren + +Nu gaan we .B2M compileren. Er zijn twee mogelijkheden de eerste beveel ik zeker voor beginners aan en maakt gebruik van het programma CONTROL dat op de schijf wordt meegeleverd. De tweede werkt zonder het programma CONTROL en wordt later besproken. We tikken: + +RUN "CONTROL" + +en laden en starten zo het programma CONTROL dat een en ander voor ons regelt. Zorg ervoor dat alles goed en wel op schijf staat voordat CONTROL geladen wordt. +1 Kies de optie 1 en zo laden we de compiler in het geheugen. +2 Kies nu optie 2 om te gaan compileren. + +CONTROL geeft aan dat de te compileren programma(deel) geladen moet worden en dan gecompileerd kan worden. We laden dus de .B2M en tikken vervolgens: + +_COMP (of CALL COMP) + +We krijgen na een korte tijd de cursor terug na de prompt als alles bij compilatie goed ging en anders een normale basicfoutmelding met het regelnummer waar het fout ging. Bij een vermoedelijk correcte compileslag zien we geen foutmelding, nu starten we wederom CONTROL met + +RUN "CONTROL" of door F3 te in te drukken + +We kiezen voor de zekerheid eerst optie 3 om te zien hoe de compilering verlopen is. Eventueel kunnen de gegevens genoteerd worden, maar dit zal in het begin zelden echt nodig zijn. + +Wegschrijven + +Nu gaan we het machinetaaldeel wegschrijven naar diskette. Hiervoor kiezen we optie 4. Het programma vraagt om een naam. We kiezen de extensie .MEM omdat dit deel straks ook met _MEM opgeroepen zal gaan worden. + +Restant basic aanpassen + +Nu gaan we .B3M aanpassen. Het programma moet straks het machinetaaldeel kunnen oproepen. Hiervoor zijn een aantal dingen noodzakelijk. Ten eerste moet het machinetaaldeel aangeroepen worden. Zoals reed eerder vermeld kan dit met _MEM, maar dan moet dit wel in het geheugen staan en de machine moet weten waar hij moet zoeken naar die MEM. Ik neem even aan voor het gemak dat het machinetaaldeel wordt ingeladen op de plaats waar hij destijds ook naar toe werd gecompileerd namelijk pagina 3. In .B3M nemen we dan op de regel: + +xxx OUT &HFD,3:_MEM:OUT &HFD,2 + +Met de OUT kiezen we pagina 3 en na de _MEM zetten we weer netjes de keuze op de oorspronkelijke pagina 2. We zetten dit programma nu op schijf met de extensie .B4M. De B4M komt van Basic 4 (for) Memory. In veel gevallen zal op deze manier het programma reeds kunnen werken. We kunnen dus RUN proberen. Stel dat alles naar wens werkt en u zet tevreden de machine uit. Later wilt u nogeens genieten van het programma en dan blijkt het ineens niet meer te werken. De verklaring is simpel; het gecompileerde deel is niet aanwezig en kan dan ook niet werken. Als we met een schone (net aangezette en niet alleen geresette) machine beginnen zal ons MEM-deel natuurlijk niet aanwezig zijn. Maar direct na compilatie staat het nog wel in het geheugen. We moeten er trouwens ook voor zorgen dat ons basicprogramma op een goede plaats in het geheugen staat. Voor beide kunnen we zorgen door een laadprogramma, een voorbeeld laadprogramma staat op de schijf onder de naam : LOADER.BAS. Voor ik hier aan toekom eerst nog eens de extensienamen op een rijtje. +Overzicht extensienamen + + .BAS het programma waar we vanuit gaan. Werkt in principe alleen met de interpreter. + .B1M het programma dat de eerste aanpassing heeft ondergaan. Moet inprincipe nog werken met de interpreter. Het te compileren deel staat in een subroutine die met GOSUB rnr wordt aangeroepen. + .B2M het programmadeel dat gecompileerd moet worden. Is in feite de subroutine uit .B1M waar de indien nodig DEFINT AZ en de DIM in is opgenomen en de RETURN uit verwijderd is. + .B3M het deel van .B1M dat niet gecompileerd gaat worden. + .B4M het resterende basicdeel .B3M waarbij de aanroep van het gecompileerde deel is opgenomen. + .LDR het programma dat alles op de juiste plaats in het geheugen laadt en de .B4M opstart. + +Werking LOADER.BAS + +Het programma begint in regel 20 te kijken of het op de goede plaats in het geheugen staat. Als dit niet het geval is doet het een tweetal POKE's in regel 30 en herlaadt zichzelf op de juiste plaats. Staat de LOADER.BAS op de goede plaats wordt het machinetaaldeel ingeladen in regel 60 op de door ons gewenste pagina. Met de OUT &HFE,3 wordt er voor gezorgd dat het op pagina 3 komt. Wilt u om welke reden dan ook een andere pagina moet u dat hier aangeven met de waarde achter de OUT &HFE. In regel 80 zorgen een tweetal POKE's ervoor dat het basicdeel .B4M op de correcte plaats kan worden ingeladen en dan wordt .B4M in regel 90 geladen en gelijk gestart. + +Eigen loader maken + +We laden LOADER.BAS in en passen het aan onze wensen aan. +regel 10 : verander in de REM het algemene 'loader' voor de door u gewenste naam en zet er eventueel eigen naam en datum bij. +regel 20 : ongewijzigd laten +regel 30 : ongewijzigd laten +regel 40 : zet hier de naam waaronder straks dit laadprogramma onder wordt weggeschreven. Het is aan te raden dezelfde naam als bij de andere files van deze serie te gebruiken, maar nu met extensie .LDR. +regel 50 : ongewijzigd laten +regel 60 : zet achter de OUT &HFE, het gewenste paginanummer. Welke paginanummers gekozen kunnen worden hangt af van de grootte van het geheugen van uw computer. Bij de Sony HB-700P (256 Kbyte) tot en met 15, Bij de Philips NMS 8235 (128 KByte) tot en met 7 en bij nog kleinere geheugens (64 KBbyte) slechts tot en met 3. Bij een correct uitgevoerde memoryexpansion kan misschien een veel grotere waarde gebruikt worden. Tevens moet u de naam van de file met extensie .MEM achter de BLOAD nog aanpassen in de door u gebruikte filenaam. +regel 70 : ongewijzigd laten +regel 80 : ongewijzigd laten +regel 90 : vul hier de naam van de gewenste .B4M in. Voor deze filenaam kan zowel voor RUN als LOAD gekozen worden. + +Schrijf tot slot de loader onder de in regel 40 gebruikte naam weg op schijf. Met de besproken aanpassingen heeft u nu de beschikking over een loader die geschikt gemaakt is voor uw programma. +Klaar + +Als alles goed gegaan is bent u nu klaar. Ter controle zet u de bestanden .LDR, .B4M en .MEM op een andere schijf en zet de computer enige tijd uit. Na enige tijd, meer dan een minuut wachten a.u.b., tikt u hoopvol RUN "naam.LDR" en was alles goed dan zal het nu perfect gaan. Als we willen kunnen we tot slot nog besluiten de files .B4M en .LDR te combineren. + +Combineren .LDR en .B4M + +In bijna alle gevallen is het mogelijk deze twee bestanden te combineren. Bedenk echter dat het programma zichzelf herlaadt en dat dat relatief veel tijd kan kosten als het programma groot is. Daarnaast is het later misschien niet altijd even duidelijk welke POKE's nu voor het laden nodig waren en welke POKE's voor iets anders. Het kan dus wel, maar doe het niet te snel. Een probleem hierbij is ook dat het basicprogramma in de gekozen opzet soms vanaf adres &HC000 staat en dan niet al te groot mag, zeg maar rustig klein moet, zijn. In dat geval kan de extra uitbreiding met de .LDR net te veel zijn. Moeilijk zal het echter niet zijn en u kunt met een klein experimentje snel uitvinden of het gaat of niet. + +Programma kent alleen ondersteunde statements + +Dit is gelukkig een stuk gemakkelijker. We laden de compiler met het programma CONTROL en compileren ons .BAS programma. Dan weer CONTROL laden en de gecompileerde versie op schijf zetten met de .MEM extensie. De loader laden en aanpassen voor ons .MEM deel. en nu starten we die natuurlijk wel direct op vanuit de loader. +Samenvatting gebruik MCBC. + +Ik geef nog even een overzicht van de stappen die genomen moeten worden om een programma dat in MSXBasic is geschreven geheel of gedeeltelijk gecompileerd te krijgen met behulp van MCBC. Zorg liefst voor een lege schijf waar vervolgens de files MCBC.BIN , LOADER.BAS en CONTROL op staan. +We beginnen nu, anders dan bij de voorafgaande uitleg met de simpele variant waar een programma geheel geschikt is voor compilatie door MCBC. + +Zet het te compileren programma op de disk + +RUN "CONTROL" + +1 Laad MCBC.BIN met optie 1 van CONTROL + +2 Stop CONTROL met optie 2 + +LOAD "naam.BAS" Laad programma dat gecompileerd moet worden + +F2 compileer u kunt ipv F2 ook zelf _COMP geven + +F3 run CONTROL + +4 kies de SAVEoptie + +prog.MEM zet het gecompileerde met de extensie .MEM op disk + + (5 run de gecompileerde versie ter controle) + +LOAD "LOADER.BAS" + +Pas LOADER.BAS in ieder geval op de volgende punten aan + verander de naam van de .MEM in de door u gebruikte naam + verander indien nodig het paginanummer waar .MEM wordt ingelezen. Het moet overeenstemmen met het paginanummer van de _MEM verderop in de loader + verander de naam LOADER.BAS in de naam van je eigen programma met de extensie .LDR zowel achter de LOAD als achter de REM in de eerste regel + zorg dat de _MEM in de zelfde pagina werkt als waar .MEM werd ingelezen + verander de naam LOADER.BAS in de naam van je eigen programma met de extensie .LDR + verander het inlezen en starten van de .B4M file in de laatste regel in een _COMP na het instellen van de juiste pagina + +SAVE "prog.LDR" + +zet de computer uit + +wacht minstens ëën minuut + +zet de computer weer aan + +RUN "prog.LDR" + +Is nergens een fout gemaakt moet alles nu goed werken. +Vervolgens de lastige variant, waar een programma niet geheel geschikt is voor compilatie door MCBC. Ook hier liefst zorgen voor een lege schijf, waar vervolgens de files MCBC.BIN , LOADER.BAS en CONTROL op gezet worden. + +Zet het te compileren programma op de disk met de extensie .BAS + +Bepaal ruwweg het te compileren deel en isoleer dat vervolgens in een subroutine aan het eind van het programma. + +Breid het programma uit met het veilig doorgeven van de noodzakelijke gegevens aan de te compileren subroutine Bijvoorbeeld met een aantal POKE's, VPOKE's of OUTs. + +Breid de te compileren subroutine uit met het correct ophalen van de noodzakelijke gegevens uit het programma. Bijvoorbeeld met een aantal PEEKs, VPEEK's of INs. + +Herhaal deze laatste twee punten ook de andere kant op van de te compileren subroutine naar het programma indien nodig. + + (RUN het programma ter controle of alles nog (zij het trager) werkt.) + +SAVE deze versie met de etensie .B1M. + +DELETE het niet te compileren deel + +Breid indien nodig het overbijfsel uit met bijvoorbeeld DIM's en een DEFINT en zorg ervoor dat altijd bij de laatste regel geëindigd wordt. + +SAVE dit deel nu met de extensie .B2M. + +Laad de versie .B1M + +DELETE nu juist het te compileren deel + +SAVE met de extensie .B3M + +RUN "CONTROL" + +1 Laad MCBC.BIN met optie 1 van CONTROL + +2 Stop CONTROL met optie 2 + +LOAD "naam.B2M" Laad programmadeel dat gecompileerd moet worden + +F2 compileer u kunt ipv F2 ook zelf _COMP geven + +F3 run CONTROL + +4 kies de SAVEoptie + +prog.MEM zet het gecompileerde met de extensie .MEM op disk + +LOAD "LOADER.BAS" + +Pas LOADER.BAS aan verander de naam van de .MEM in de door u gebruikte naam + verander indien nodig het paginanummer waar .MEM wordt ingelezen. Het moet overeenstemmen met het paginanummer van de _MEM in .B4M + verander de naam LOADER.BAS in de naam van je eigen programma met de extensie .LDR zowel achter de LOAD als achter de REM in de eerste regel + verander de naam van de file in de laatste regel in de naam die door u gebruik gaat worden voor de .B4M file + +SAVE "prog.LDR" + +Laad de file met de extensie .B3M + +Vervang in dit programma mistens de GOSUB rnr die de nu gecompileerde subroutine aanriep door een OUT &HFD,x en een _MEM. Zorg ervoor dat het paginanummer overeenstemt met het paginanummer dat in de loader gebruikt werd om te lezen. + +SAVE onder de extensie .B4M + +zet de computer uit + +wacht minstens ëën minuut + +zet de computer weer aan + +RUN "prog.LDR" + + +is nergens en fout gemaakt moet alles nu goed werken. +MCBC zonder CONTROL. + +Ook zonder steeds opnieuw met control te werken is het goed mogelijk MCBC te gebruiken. Hoe in dit geval MCBC op de juiste plaats ingeladen moet worden kunt u in CONTROL vinden. Als deze tip niet voldoende is kunt u er beter niet aan beginnen MCBC te gebruiken zonder CONTROL. Als de compiler echter eenmaal in het geheugen staat kan een basicprogramma dat gecompileerd kan worden er tegelijk bij in het geheugen staan. De compiler staat in pagina 2 en de gecompileerde versie komt in pagina 3 en eventueel pagina 4 als pagina 3 te klein is dat wil zeggen dat de objectcode meer dan 16 Kbyte groot is. +U start de compiler met _COMP nadat de juiste pagina is ingesteld, dus we tikken: + +OUT&HFD,2:_COMP + +Heeft u eenmaal een oorspronkelijke versie van CONTROL laten lopen kunt u hiervoor ook F1 en F2 gebruiken. Om de gecompileerde versie te starten tikken we: + +OUT &HFD,3:_MEM:OUT &HFD,2 + +Of na CONTROL simpel F6,F7 en F1 + +Na deze laatste OUT (of F1) kan direct weer _COMP gegeven worden maar om fouten te voorkomen is toch voor alle zekerheid de OUT&HFD,2 voor de _COMP gezet. + +FD en FE + +Met OUT &HFE, geven we voor BLOAD "xxxx.MEM" aan in welke geheugenpagina geladen moet gaan worden en met OUT &HFD, geven we voor de _MEM aan in welke pagina gekeken moet worden. Haal deze twee niet door elkaar een fout is hier zo gemaakt. Pas bij het zelf POKE'n en OUT'n op dat u geen vergissingen maakt. In de loader wordt gebruik gemaakt van de OUT &HFE en in CONTROL van OUT &HFD. Een vergissing is niet altijd snel hersteld en komt bijna altijd ongelegen. Save daarom altijd uw tussenresultaten op tijd, dus regelmatig en zeker vlak voor een 'RUN', POKE of OUT. + + + +Routines + +Veel problemen zullen regelmatig voorkomen. Dit betreft zowel zaken die eens hebt geprogrammeerd en die handig in andere programma's zijn op te nemen zoals ook in normaal basic geldt. Maar ook zijn er de oplossingen die u ontwikkelde om bepaalde niet ondersteunde statements te ondervangen. Het is slim om deze oplossingen redelijk gebundeld te houden om dan in voorkomende gevallen direct te kunnen gebruiken. Ook zou je zo een 'uitbreiding' van basic kunnen maken door een code aan te maken die iets doet wat zelfs in standaard basic niet ondersteund wordt. Als voorbeeld : stel dat de PAINT niet in MSX-basic bestond, je kan dan een routine in basic maken die een vlak voor je opvult. Deze routine compileer je dan en je hebt de PAINT beschikbaar met _MEM. Je kan wel de standaard PAINT nu uitbreiden tot een PAINT met een patroontje ! Of u maakt een PAINT om een gebied te arceren. En dat kan en handige toepassing zijn voortoepassingen met screendumps op een normale printer zonder kleur. + +Tijdmeting + +Bent u erg benieuwd naar de snelheidswinst kan het programma dat de .MEM aanroept voorzien worden van een timer. +Aan het begin zetten we +xxx TIME=0 +en aan het eind van het te meten deel +yyy ? TIME/50;" seconden" +Deze timer niet meecompileren omdat de meting dan niet helemaal eerlijk is. + +Problemen en hun oplossingen + +Dit betreft bijvoorbeeld een groot aantal gegevens die door middel van een READDATA combinatie in een of meer array's worden ingelezen. We kunnen in dit geval een klein programmaatje maken dat de DATA inleest en dan wegschrijft. Normaal kunnen we dan de gegevens weer inlezen om ze snel paraat te hebben maar ook inlezen van schijf kan niet met MCBC. Wel kunnen we echter de gegevens inlezen in ons .LDR programma dat we toch moeten maken. +Voorkomende vragen + +Hoe kan ik meerdere stukken van mijn programma door MCBC laten compileren? + +Niet zo moeilijk maar wel veel werk. Splits eerst een deel van het programma waar u van uit gaat af en behandel dat op de hopelijk nu bekende wijze. Als alles goed werkt beschouwen we de .B4M file als een nieuwe .BAS en gaan weer net zo te werk als zoëven. Het probleem schuilt hier in de extensienamen waar we er een zo grote hoeveelheid van krijgen dat we door de bomen het bos niet meer zien. Ik stel voor alle versies van de eerste gang te laten verdwijnen met twee uitzonderingen de loader xxxx.LDR en de machinetaalroutine xxxx.MEM moeten blijven. Het best is het waarschijnlijk om weer een nieuwe schijf te gebruiken waar in het begin alleen de volgende vijf files op staan : MCBC.BIN, CONTROL, xxxx.LDR, xxxx.MEM en xxx.B4M. Hernoem de xxxx.MEM in xxxx.M1M en de xxxx.B4M in xxxx.BAS. Noem het resultaat van de compilatie nu .M2M en zorg er voor dat de nieuwe loader beide .MxMfiles in verschillende pagina's inleest en de nieuwe .B4M ook beide aanroept. Herhaal dit proces net zo vaak als nodig is voor een derde, een vierde, enz. machinataalroutine. + +De compilatie verliep uitstekend maar ik kan mijn programma niet meer onderbreken. Wat nu? + +Jammer dan. U kunt resetten en zowel de in uw ogen niet perfecte objectcode als eventueel MCBC blijven in het geheugen aanwezig. Voorkom dit soort problemen door een stop in uw programma in te bouwen. + +Bij de laatste poging liep mijn object code vast of beter gezegd bleef maar doorlopen en was niet te onderbreken. Ik heb toen gereset en wil nu een te onderbreken versie maken. Hoe doe ik dat? + +Dit kan op verschillende manieren met elk hun eigen nadelen. +Alle methodes hebben als nadeel dat de object code er trager door zal worden, soms echter zo weinig dat dat niet merkbaar is. +Een programma dat blijft doorlopen zal een lus moeten bevatten. In deze lus kunt u een keyboardscan doen en bij positief resultaat de lus verlaten. Uw .B2M ziet er als volgt uit: + +.......... +130 ..... + ..... de lus die blijft doorlopen +220 ..... +..... +440 REM einde + +In dit geval voegt u bijvoorbeeld vlak voor regel 220 regel 215 toe. + +215 IF INKEY$=<>"s" GOTO 440 + +De lus kan nu wel verlaten worden door het indrukken van de kleine letter s. Deze controle is wel traag en zal dus remmend werken, of dat storend is zult u zelf moeten beoordelen. Een andere mogelijkheid is het onderbreken op tijd. Gemakkelijk te programmeren is bijvoorbeeld in het begin zetten van de tijd opeen of andere waarde. Dit zetten doet u bij voorkeur in .B4M omdat het dan later nog aangepast kan worden. +In .B4M neemt u op + +rnr TIME=y + +met y een waarde van 0 tot 65536 en een regelnummer zo dat deze regel voor de CALL MEM komt. In .B2M neemt u vervolgens op de regel + +215 IF TIME=0 GOTO 440 + +Als de y groot gekozen wordt zal er snel een onderbreking volgen. Bij de keuze y=0 zal het een ruime twintig (65536/50/60) minuten duren voordat er onderbroken wordt. Denk er wel aan dat gedurende het zetten van de tijd en het uitlezen ervan ook enige tijd verloopt en de nul zo gepasseerd kan worden. Een zeer snelle test is een PEEK op adres &HFC9F waar een deel van de TIME staat. + +In .B2M neemt u op de regels + +rnr TIME=0 +215 IF PEEK(&HFC9F)=y GOTO 440 + +en uw lus zal na iets meer dan y maal 5 seconden onderbroken worden. N.B. De TIME=0 natuurlijk niet in de lus zetten! + + + +Help. +Ik kom er echt niet meer uit. +Zit er een fout in MCBC ? + +Tot slot als u er echt niet meer uitkomt en een fout in MCBC vermoedt. + +Als u hulp nodig hebt en mij of een ander daarover benaderd zal het voor ons absoluut noodzakelijk zijn u zich aan de extensieconventie gehouden hebt. Anders zal steevast de reaktie zijn : zorg eerst voor de juiste extensies en neem dan weer contact op. Zorg er trouwens ook voor de gegevens uit CONTROL bij de hand te hebben als u hulp nodig hebt. Bel voor problemen met MCBC bij voorkeur op de maandagavond. + +Frank H. Druijff + + +Gebruikte termen + +alloceren toewijzen van geheugenruimte. +assembly languageen taal waarbij we haast direct in machinetaal met behulp van mnemonics programmeren +.BAS bestandsnaamextensie voor programma's in BASIC. +.B1M bestandsnaamextensie voor programma's in BASIC die voorbereid zijn voor (gedeeltelijke) compilatie met MCBC. +.B2M bestandsnaamextensie voor programma of deel ervan in BASIC dat u wilt gaan compileren. +.B3M bestandsnaamextensie voor programmadeel in BASIC dat niet gecompileerd wordt (.B1M.B2M) +.B4M bestandsnaamextensie voor programma(deel) in BASIC dat het niet gecompileerde deel basic bevat met de aanroep(en) voor het machinetaaldeel. +BIOS Basic Input Output System. +BIOSROM De ROM waar de BIOS in staat. +compiler het programma dat een in een hogere programmeertaal geschreven programma kan omzetten in machinetaalcode +control het programma dat voor ons de compiler laadt en informatie geeft over de compilatie en de objectcode voor ons wegschrijft. +defaultwaarde waarde die aangenomen wordt als er geen (nieuwe) waarde genoemd wordt. +extensie het laatste deel van de naam van een file het 'woordje' staat achter de punt en is maximaal drie tekens lang. +extensieconventie de afspraken hoe de verschillende files een onderscheidende extensie krijgen. +expressie uitdrukking, een berekening waarmee een of andere waarde berekend kan worden. +integergetal zonder breukdeel tussen 23768 en 32767. +interpreter het programma dat in de computer zit ingebouwd zodat hij in staat is programma's die in MSXBasic zijn geschreven regel na regel en instructie na instructie te interpreteren en uit te voeren. +LOADER.BAS Een programma dat zichzelf realloceert en de diverse andere files inlaadt en opstart. +Loader (.LDR) Een programma om een ander programma in de computer in te laden en meestal op te starten. +MCBCMsx Club Basic Compiler +.MEM Gebruikte filenaamextensie voor objectcode +memorymapper een voorziening die er voor zorgt dat er meer geheugen gebruikt kan worden dan de processor kan adresseren. +mnemonic een korte gemakkelijk te onthouden term voor de diverse instructies in machinetaal +modulair programmeren programmeren op een methode zodat gemakkelijk de verschillende onderdelen van een programma zijn te herkennen. +object of object code het machinetaalprogramma dat met de compilatie door MCBC van uw BASIC gevormd wordt. +realloceren opnieuw toewijzen van geheugenruimte. In de praktijk zet op een andere plaats in het geheugen. +RAM Random Access Memory, het door de gebruiker te vullen geheugenROMRead Only Memory populair gezegd de geheugens waar de routines in staan die het systeem zelf laten draaien. +source of source code het MSXBASICprogramma dat u wilt gaan compileren met MCBC. +stack de 'stapel' met gegevens waarvan altijd de bvenste wordt gepakt. +syntax de grammaticale regels voor notatie in een taal. +Z80 De centrale processor in de MSXcomputer. diff --git a/sunrise_special/4/DOS2 Batchfiles.md b/sunrise_special/4/DOS2 Batchfiles.md deleted file mode 100644 index 97fd462..0000000 --- a/sunrise_special/4/DOS2 Batchfiles.md +++ /dev/null @@ -1,381 +0,0 @@ - D O S 2 B A T C H F I L E S - - - Op Sunrise Special #2 heeft al eens een tekst over de - mogelijkheden van MSX-DOS 2.31 gestaan. Ook stond op SRS#2 - een tekst over pipelining en redirectioning. Ik zal in deze - tekst echter wat praktijkvoorbeelden ervan geven: de - batchfiles die op mijn HD staan. - - Eigenlijk is dit alleen interessant voor HD-gebruikers, want - batchfiles nemen toch minstens 1 kB in van een diskette, en - het kost weer extra laadtijd. Op een harddisk maakt de - diskruimte niet bar veel uit, en de laadtijd is vrij kort. - - - D R I E S O O R T E N - - Je kunt batchfiles opdelen in drie soorten. De eerste zorgt - ervoor dat een aantal commando's gecombineerd worden zodat - er minder hoeft te worden getikt. De tweede soort zorgt ook - voor minder typewerk, maar heeft als doel het opstarten van - een programma, en eventueel nog iets doen na het be�indigen - ervan. En de derde soort is gewoon diversen. - - Dit opdelen in soorten is eigenlijk flauwekul, omdat het - natuurlijk op heel veel manier kan, maar ik heb het gedaan - om toch een beetje een overzichtelijke tekst te kunnen - typen. - - - F O R M A A T - - Ik houd zelf het volgende aan: namen van files, directory's - of drives met hoofdletters en interne DOS commando's met - kleine letters. Maar in deze tekst type ik alles gewoon met - hoofdletters, dit voor de duidelijkheid. - - - E E R S T E S O O R T - - Ik zal gewoon een aantal batchfiles bespreken. Deze staan - ook op deze disk onder dezelfde naam. - - - D M O V E . B A T - - COPY %1 %2 - ECHO Y|DEL %1>NUL - - MOVE kan normaal alleen files op ��n disk verplaatsen, dus - van de ene dir naar de andere directory. MOVE verplaatst dan - ook alleen de directory-entry. Ik verplaats echter vaak - files van de ene drive naar de andere. Dat kost normaal 2 - regels typewerk. Met DMOVE wordt dit gereduceerd tot ��n - regel. - - %1 is de eerste parameter die achter de batchfile staat. %2 - de tweede, enz. %0 is trouwens de ECHTE eerste parameter. - Hier zal ik later ook nog iets mee doen. - - COPY %1 %2 zorgt dus gewoon dat er een file gekopieerd - wordt. ECHO Y|DEL %1>NUL betekent dit: - - ECHO Y| stuur het teken y naar de input van het commando - dat erachter staat (pipelining). - - DEL %1 als de vraag "Erase all files (Y/N)? " komt, zal - hier automatisch een Y worden gegeven. - - >NUL stuur de output van de voorgaande commando's naar - het NUL device. Dit houdt in dat er niks op het - schemr komt. - - - M O V D I R - - MD %2 - MOVE %1 %2 - RD %1 - - Deze batchfile gebruik ik om snel een directory in een - andere directory te plaatsen. Als je bijvoorbeeld eerst de - subdirectory TSRS in de rootdir hebt staan, en je wilt deze - verplaatsen naar de subdir MEMMAN, doe je het volgende: - - MOVDIR \TSRS \MEMMAN\TSRS - - Nu wordt eerst de directory TSRS aangemaakt in MEMMAN, dan - worden alle files gemoved van \TSRS naar \MEMMAN\TSRS en - tenslotte wordt de directory \TSRS verwijderd. - - Eventueel zou dit ook nog uitgebreid kunnen worden naar - DMOVDIR, die ik zelf echter niet op mijn HD heb staan, omdat - bij MOVE de FAT niet veranderd wordt, en bij COPY wel. En - een directory blijft meestal toch op dezelfde drive staan. - Maar voor de volledigheid... - - - D M O V D I R - - MD %2 - COPY %1 %2 - ECHO Y|DEL %1>NUL - RD %1 - - - D I V E R S E N - - Eigenlijk zou nu natuurlijk de tweede soort moeten komen. - Maar omdat die files gebruiken die moeten worden aangewezen - met het environment item PATH en er zijn nog een paar andere - environment items nodig. - - - A U T O E X E C . B A T - - BUFFERS 18 - - Zorgt ervoor dat het aantal buffers wordt vergroot. Dit - staat standaard op 5. In de buffers worden de FAT- en - directorysectoren bewaard, wat de laadtijd zeer ten goede - komt. - - IF NOT %TIME%A==24A A:\UTILS\ST4TUNE - - ST4TUNE.COM is een programma dat Star Trek quotes laat zien. - Er wordt telkens willekeurig ��n gekozen. Soms is het nodig - om AUTOEXEC.BAT nog eens op te starten, bijv. als de - environments items verneukt zijn. Als TIME dan nog goed - staat, wordt ST4TUNE niet gerund, omdat het toch ietwat - traag (CP/M) is. - - PATH H:\UTILS; A:\; A:\BATCH; A:\UTILS - PATH +A:\UTILS\TEXT; A:\UTILS\CRUNCH; A:\UTILS\ML - PATH +A:\UTILS\TURBOR; A:\UTILS\DOS2TOOLS; A:\BASIC - - Een aantal directory's in PATH zetten. BATCH moet uiteraard - VOOR UTILS staan, omdat sommige batchfiles gelijknamige COM - files gebruiken. Bijv. PMARC.BAT; zie verderop. Ook moet - eerst op de RAMdisk worden gezocht. - - ASSIGN F: G: - - Bij mij is E: de eerste echte diskdrive. Omdat ik maar ��n - diskdrive heb, is F: een virtuele drive. Dat betekent dat - ik, als ik naar F: vraag, de mededeling "Insert disk in - drive F: and strike a key when ready" krijgt. Dat vind ik - niet leuk, en daarom laat ik F: naar G: wijzen. Omdat G: - niet bestaat, bestaat F: nu ook niet meer voor lagere - systeemfuncties. - - Bij Disk I/O error wijst de computer overigens wel weer naar - de echte drive. Als je bijv. ASSIGN C: A: hebt gedaan, je - gaat naar C: en er is een Disk I/O error krijg je toch - "drive A:" op het scherm. - - Met ASSIGN zonder een drive (of letter) erachter wordt het - trouwens weer default gezet. - - SET TIME 24 - - Ik ben mijn horloge gewend, en heb liever niet am en pm - meldingen. - - SET DATE DD-MM-YY - - De Nederlandse manier van data. - - SET SHELL H:\UTILS - - COMMAND2.COM staat zo direct in H:\UTILS. - - SET PROMPT ON - - Prompt aan. Dus niet "A>", maar "A:\>". - - SET PATTERN C:\DIVERSEN\CHARSET - - Tja, PATTERN.COM is een programma dat nog niet is - vrijgegeven. Ik denk wel dat het op de volgende Special - staat. - - SET EXPERT ON - - Expert mode aan. COM files die van DOS1 disks worden - opgestart werken gewoon. - - SET TEMP H:\ - - Tijdelijke bestanden (o.a. bij pipelining gebruikt) in H:\. - - SET HELP C:\TEKST\HELP - SET KHELP %HELP% - - Japanse HELP (Kanji HELP) files hoef ik niet... Die zijn dus - hetzelfde als de Engels HELP files. - - IF NOT A%MEMMAN%==AON SET MEMMAN OFF - - Het environment MEMMAN wordt op OFF gezet als het niet aan - stond. MEMMAN wordt ON gezet door MEMMAN.BAT. - - RAMDISK 384 - - MD H:\UTILS - COPY A:\COMMAND2.COM H:\UTILS - COPY A:\UTILS\DOS2TOOLS\KEY.COM H:\UTILS - - RAMdisk aanmaken, en 2 files erop zetten. Ik wilde eerst - functietoetsen gebruiken onder DOS. Moet ik weer in orde - maken. - - ECHO N|PATTERN STANDARD>NUL - - Ik laad de standaard karakterset in, omdat ik anders gek - word van het yen-teken. - - KEY ON - - Functietoetsen aan en dan zit ik in DOS. - - - R E B O O T . B A T - - MODE 80 - TURBOSW 2 - COLOR 15,0,0 - - Scherm weer goed zetten, R800-DRAM aan. - - SET R1=%REBOOT% - SET REBOOT= - - Via het env. item REBOOT kan een commando worden meegegeven - dat wordt uitgevoerd als je terug naar DOS gaat. REBOOT - wordt in een ander item gekopieerd omdat je anders het - effect zou kunnen krijgen dat er de volgende keer weer - hetzelfde wordt gedaan als je terug naar DOS gaat. - - %R1% - - SET R1= - - Het env. item R1 wordt gewist als er nog wordt teruggekeerd - naar de batchfile of als R1 een intern DOS commando was. - - - T W E E D E S O O R T - - Nu worden batchfiles besproken die een ander programma - inladen. Om te beginnen een hele simpele. - - - P M A R C . B A T - - SET UPPER ON - PMARC.COM %1 %2 %3 %4 %5 %6 %7 %8 %9 - SET UPPER OFF - - Het item UPPER is ervoor om te zorgen dat alle kleine - letters die in parameters voorkomen in hoofdletters worden - omgezet. Dit is voor sommige CP/M programma's, die anders - niet goed functioneren. Hiertoe behoren PMARC en PMEXT. - - Omdat het voor sommige programma's ook mooi is om kleine - letters te kunnen gebruiken (waaronder INPUT.COM, zie - Sunrise Magazine #6), wordt UPPER ook weer op OFF gezet. - - - M E M M A N . B A T - - IF %MEMMAN%==ON ECHO - IF %MEMMAN%==ON ECHO *** MemMan already installed - IF %MEMMAN%==ON EXIT - - Als MemMan al eens is ingeladen, wordt teruggekeerd naar - MSX-DOS. Dit gebeurt met EXIT. Als je COMMAND2 intypt zonder - iets extra, kost dat geheugen, en bij EXIT wordt dit weer - vrijgegeven. Probeer voor de lol trouwens een COMMAND2>PRN. - Zorg wel dat de printer aan staat! Als je dan ECHO Tekst>CON - intypt, krijg je w�l weer iets op het scherm. Achter EXIT - kan ook nog een foutcode worden opgegeven. - - CLS - - PATH +A:\MEMMAN - SET MEMMAN=ON - SET REBOOT=%1 - SET TL=A:\MEMMAN\TSRS - - Het path wordt uitgebreid met A:\MEMMAN. De TSR directory - wordt goed gezet en de parameter die is meegegeven achter - MEMMAN.BAT wordt in REBOOT gezet. - - MEMMAN.COM - - - A F T E R M M . B A T - - Mijn MEMMAN.COM zet '_SYSTEM("AFTERMM.BAT")' in de - keyboardbuffer. AFTERMM betekent "after MemMan". - - CLS - ECHO Loading CHGCPU2.TSR and MBTSR.TSR... - - TL CHGCPU2>NUL - TL MBTSR>NUL - - Laad een paar TSR's in. - - REBOOT - - REBOOT opstarten. Het commando dat eerst achter MEMMAN.BAT - stond wordt dan via REBOOT.BAT uitgevoerd. Hier volgt een - batchfile die een MemMan programma uitvoert... - - - M P . B A T - - IF %MP%A==A SET MP=%1 - IF %MP%A==A SET MP=B:\MOD - - Als MP leeg is, wordt de parameter achet MP.BAT in MP gezet. - Als MP nu nog leeg is, en dus niks in de parameter zat, - wordt MP gevuld met de directory waar MOD files in staan. - - IF NOT %MEMMAN%A==ONA MEMMAN MP - - Als MemMan nog niet in het geheugen zat, wordt het nu - geladen. Bij terugkomst in DOS wordt MP.BAT weer uitgevoerd. - Vandaar ook dat %1 in een environment item wordt gezet. - - MP2.COM %MP% - - MP2.COM is een ietwat aangepaste versie van de MOD-player. - - SET MP= - - %MP% wordt weer gewist. - - - M C M . B A T - - Dit programma laadt MCM-Index in. - - PPDIR PUSH - - De huidige directory bewaren. - - CDD H:\ - - Overgaan op H:\. CDD wordt besproken op Sunrise Special #2. - - IF NOT EXIST MCM.COM COPY C:\DIVERSEN\MCMINDEX\MCM.COM - IF NOT EXIST MCM.DAT COPY C:\DIVERSEN\MCMINDEX\MCM.DAT - IF NOT EXIST MCM.SET COPY C:\DIVERSEN\MCMINDEX\MCM.SET - IF NOT EXIST TREF.NDX COPY C:\DIVERSEN\MCMINDEX\TREF.NDX - IF NOT EXIST SOORT.NDX COPY C:\DIVERSEN\MCMINDEX\SOORT.NDX - - Als bovenstaande files nog niet in H:\ staan, worden ze - gekopieerd van de directory C:\DIVERSEN\MCMINDEX. MCM Index - werkt namelijk een stukje sneller vanaf RAMdisk. - - KEY OFF - - Het programma kan niet tegen functietoetsen onder DOS. - - H:\MCM.COM - KEY ON - PPDIR POP - - Directory herstellen. - - - G E N O E G - - Ik hoop dat dit genoeg is om zelf handige batchfiles te - kunnen maken. Als er echter vragen zijn, schrijf dan naar de - postbus of het bel Sunrise BBS Nuth. - - Kasper Souren diff --git a/sunrise_special/4/De Programmeertaal C deel 5.md b/sunrise_special/4/De Programmeertaal C deel 5.md deleted file mode 100644 index 7a4adea..0000000 --- a/sunrise_special/4/De Programmeertaal C deel 5.md +++ /dev/null @@ -1,679 +0,0 @@ - D E P R O G R A M M E E R T A A L C - - D E E L 5 - - - - N.B.: Dit is het vijfde deel van de serie. Bekendheid met de - eerste vier delen wordt verondersteld! - - - C O M P L E X E D A T A T Y P E N I N C - - - I N L E I D I N G - - De kracht van C zit hem in het feit dat er zowel 'dichtbij' - de machine geprogrammeerd kan worden (waardoor er veel - minder vaak naar assembler hoeft te worden gegrepen) als - heel abstract, iets wat PASCAL programmeurs vaak als hun - specifieke terrein beschouwen. - - In feite heeft PASCAL maar twee dingen voor op C: - enumeraties en sets. Enumeraties zijn gemakkelijk te - vervangen door constanten, sets geven wat meer problemen, - maar in C zijn wel uitgebreide bitmanipulaties mogelijk die - dit gemis kunnen opvangen - en een stuk efficienter. (In - ANSI C heeft men de taal overigens uitgebreid met - enumeraties, maar ANSI C is niet voor de MSX te krijgen.) - - Bij voorbaat wil ik de gebruikers van Small C waarschuwen - dat het meeste van wat in deze aflevering staat niet geldt - voor deze compiler: buiten het enkelvoudige array kent Small - C geen samengestelde datatypen, geen casts, geen - initializers en is het geheugenbeheer - mogelijk afhankelijk - van de verschillende versies - beperkt. - - - S A M E N G E S T E L D E T Y P E N - - Of we abstract kunnen programmeren hangt er vooral vanaf of - we onze gegevens astract kunnen maken. Blijven we steken op - het niveau van bits, bytes of words (machinetaal, maar ook - BASIC) dan maken we het onszelf heel moeilijk om - begrijpelijke en dus foutloze programma's te schrijven als - we wat meer gecompliceerde algorithmen willen gebruiken. - - - A R R A Y 'S , P O I N T E R S E N D E "C A S T " - - Array's en pointers zijn natuurlijk in deel drie al - behandeld, toch komen hier nog een paar dingen aan de orde - die niet eerder aan bod zijn gekomen. - - In de eerste plaats moet ook binnen declaraties rekening - worden gehouden met de prioriteit en volgorde van - "evaluatie" van de "operatoren". Ik gebruik hier - aanhalingstekens omdat er natuurlijk niet echt sprake is van - een rekenkundige uitdrukking, maar het lijkt er veel op. - - In declaraties komen gelukkig alleen de '()', de '[]' en de - '*' "operator" voor. De '()' en de '[]' hebben een hogere - prioriteit dan de '*'. (De '()'is de 'functie-return' - operator; deze valt echter buiten het bestek van deze - aflevering.) Gewone haakjes kunnen gebruikt worden als deze - prioriteit ons niet bevalt. De "evaluatie" verloopt voor de - '()' en '[]' van links naar rechts, die van de '*' precies - omgekeerd. Gelukkig hoeven we met dat laatste bij - declaraties geen rekening te houden, omdat het de enige - "operator" is met die prioriteit die in declaraties kan - worden gebruikt. - - Zo is na - - char *vb1[10]; - - 'vb1' een array van 10 pointers naar char, en na - - char (*vb2)[10]; - - 'vb2' een pointer naar een array van 10 chars, iets heel - anders. In het laatste geval hadden we ook kunnen schrijven: - - char (*vb2)[]; - - Er wordt namelijk geen array gedeclareerd (waarvoor geheugen - gereserveerd zou moeten worden), maar een pointer naar een - array. Binnen C hoef je in zo'n geval de grootte van het - array niet op te geven, wat logisch is: in C wordt toch niet - gecontroleerd of een array index binnen de grenzen valt! - - Het is in principe mogelijk de declaraties zo ingewikkeld te - maken als je zelf wilt, als je bovenstaande regels maar in - acht neemt. (In het bijzonder kun je dus een array maken met - twee of meer dimensies!) Het is echter bijzonder gemakkelijk - om hierin fouten te maken, of het overzicht te verliezen, - vooral omdat lang niet alle compilers meldingen geven als we - dingen (bijvoorbeeld pointers en int's) doorelkaar halen. - ASCII-C vormt hierop gelukkig een uitzondering. - - Maar stel dat we juist wel bepaalde datatypen doorelkaar - willen gebruiken? Dit komt vaker voor dan je op het eerste - gezicht denkt. Zo verwachten sommige standaardfuncties een - unsigned als een van hun parameters, maar vaak is de waarde - alleen als int beschikbaar. (Zie ook 3.1 voor een voorbeeld - hiervan.) Hoe gaan we dan te werk? - - Allereerst moet de de waarde van de int natuurlijk wel - positief zijn, want unsigned's zijn altijd positief. Is dat - het geval dan volstaat het voor de uitdrukking '(unsigned)' - te zetten. In meer algemene termen: zet een declaratie van - het gewenste type waarin een variabelenaam ontbreekt tussen - haakjes en voor de uitdrukking, en voila! We hebben van - datatype gewisseld. Deze operatie wordt een 'cast' genoemd. - - Een 'cast' kan alleen worden uitgevoerd bij enkelvoudige - datatypes (unsigned, int, char en pointers), wat logisch is, - want alleen deze mogen gebruikt worden bij een assignment - ('=' operator), of als functieparameter en -return. Ook de - 'cast' operator heeft een prioriteit, uiteraard, en die is - dezelfde is als die van '++', '--', enz. - - Overigens wordt bij een assignment meestal een automatische - cast uitgevoerd naar het gewenste type, bijvoorbeeld: - - int g1; - char g2; - - g1 = 65; - - g2 = g1; - - Hierna bevat g2 een 'A', als het systeem waarop we werken - tenminste de ASCII-code gebruikt. Waar echter nooit - automatische casts worden uitgevoerd zijn functie-parameters - en -returns, wat bij ASCII-C tot problemen kan leiden, omdat - char's aan de ene kant, en unsigned's, int's en pointers aan - de andere kant op verschillende manieren worden door- en - teruggegeven. De functie parameter checker van ASCII-C - (FPC.COM) ontdekt dit soort fouten wel, maar het is niet - verplicht deze te gebruiken! - - Bij HiSoft C moet een cast op een iets andere manier gegeven - worden: voor de haakjes moet nog het woord 'cast' worden - gebruikt. Het al eerder gebruikte voorbeeld zou dan: - 'cast(unsigned)' worden. Naar eigen zeggen is dit gedaan om - de compiler simpeler te houden, maar het komt niet overeen - met enige standaard. - - - - S T R U C T S - - Structs gebruiken we als we verschillende gegevens bij - elkaar willen opslaan. Als voorbeeld nemen we een punt in de - ruimte: deze heeft een X, Y en Z coordinaat. Gesteld dat we - genoegen nemen met int's voor deze coordinaten dan hebben we - na - - struct point { int x,y,z; } pnt1; - - een variabele 'pnt1' gecreeerd die uit drie int's bestaat - met de namen 'x', 'y' en 'z'. Deze struktuur (vandaar - 'struct') is nu bekend onder de naam 'point', zodat we met - bijvoorbeeld - - struct point pnt2; - - de variabele 'pnt2' in het leven roepen, die op precies - dezelfde manier is samengesteld. We zijn overigens niet - verplicht een struct een naam (we spreken in C ook wel over - 'tag name') te geven, maar het is vaak heel handig. - Omgekeerd kun je ook de naam van de variabele weglaten. Er - wordt dan uiteraard geen variabele gecreeerd, maar de struct - is dan wel gedefinieerd. Dit gebeurt nogal eens in - '#include' files waarin we dit soort definities voor een - aantal modules tegelijk willen vastleggen. - - Om toegang te krijgen tot het "inwendige" van een struct - - de 'members' (= leden) - gebruiken we de '.' operator - gevolgd door de naam van het lid. Als we de Z-coordinaat - willen bereiken van 'pnt1' is - - pnt1.z - - voldoende, en dit samenstel is als gewone variabele te - gebruiken. Veel algorithmen maken gebruik van lijsten of - boomstrukturen. Hiervoor is nodig dat er in de de struct een - of meer pointers zitten naar andere variabelen van hetzelfde - type. Als voorbeeld kunnen we denken aan een lijst woorden, - of namen. De pointer in de struct wijst dan naar de struct - met de volgende naam, en de pointer daarin naar de - daaropvolgende, enzovoort. (In de laatste struct maken we de - pointer NULL.) - - struct name { struct name *next; - char print_name[20]; } firstname; - - Dit geeft aan hoe we zoiets kunnen doen. Nu we het toch over - pointers hebben: er bestaat een verkorte schrijfwijze om een - member van een struct te bereiken uitgaande van een pointer - naar een struct. Hou bovenstaande struct in gedachten, en - bekijk het stukje C hieronder: - - struct name *pointer; - - pointer = &firstname; - - pointer = pointer->next; - - Het gaat hier natuurlijk om de '->'. Volledig identiek met - de laatste regel zou zijn: - - pointer = (*pointer).next; - - (De haakjes zijn nodig omdat de '.' operator een hogere - prioriteit heeft dan de '*' operator.) Het behoeft geen - betoog dat de andere schrijfwijze korter is, en zeker zo - duidelijk. - - Als een struct eenmaal 'bekend' is, of beter gezegd: - gedefinieerd is, kan een struct precies zo gebruikt worden - als een gewone variabele, al zijn er een paar restricties. - Zo kan een struct niet als parameter van een functie worden - gebruikt, maar een pointer naar een struct mag wel, en dat - voldoet in bijna alle gevallen even goed. - - Een vervelender restrictie is het feit dat de '=' operator - niet gebruikt mag worden op structs: we moeten de leden stuk - voor stuk kopieren, of gebruik maken van de 'movmem'- of - 'memcpy'-functie. (Deze functies worden verderop in deze - tekst besproken.) - - Wat wel weer mag is in de definitie van een struct een - andere struct gebruiken. Een uitgebreid voorbeeld hiervan - staat aan het eind van het volgende gedeelte. - - - - U N I O N S - - Unions lijken een beetje op structs. De manier waarop ze - gedefinieerd en gebruikt worden is zelfs precies gelijk aan - structs, als je het woord 'union' voor 'struct' invult. Het - grote verschil is dat in een struct alle leden tegelijk - bruikbaar zijn, en in een union slechts een lid tegelijk. Of - om het anders te zeggen: in een union zijn de leden 'bovenop - elkaar' gelegd, en in een struct 'naast elkaar'. - - Een voorbeeldje maakt alles misschien duidelijker: - - union char_int { char letter; - int getal; } uvar; - - We kunnen nu bijvoorbeeld doen: - - uvar.letter = 'A'; - - Nu bevat uvar.letter het karakter 'A', en is uvar.getal niet - gedefinieerd. Na - - uvar.getal = 123; - - bevat uvar.getal de waarde 123, en is de waarde van - uvar.letter niet gedefinieerd. - - Hadden we een struct gebruikt, in plaats van een union, dan - had uvar.letter nu nog steeds de waarde 'A', maar een struct - gebruikt daarom wel meer geheugen: een struct gebruikt - evenveel geheugen als de som van het geheugengebruik van de - afzonderlijke leden, een union gebruikt slechts zoveel - geheugen als het grootste lid. - - Bovenstaand voorbeeld zal wel het gebruik, maar zeker niet - de zin van de union duidelijk maken. Als leden van een union - worden dan ook meestal zelf ook samengestelde typen - (array's, structs, unions) gebruikt, al dan niet samen met - simpeler typen. Als voorbeeld een door mijzelf in een - programma gedefinieerde struct: - - struct node { char nodetype; - union { - struct { struct node *left, *right; } ptr_node; - CONSTANT con_node; - VARIABLE var_node; } nodeinfo ; }; - - CONSTANT en VARIABLE zijn met een 'typedef' (zie 2.4) - gedefinieerde types. Binnenin de struct 'node ' worden op - hun beurt een struct en een union gedefinieerd. Om de - variabele 'left' te bereiken is na de naam van de - struct-variabele nodig: '.nodeinfo.ptrnode.left', waarbij - 'nodeinfo' de naam is van de union, het tweede lid van van - de struct 'node', 'ptrnode' de naam wan het eerste lid van - de union, en zelf een struct, en 'left' de naam van het - eerste lid van de binnenste struct. Het is even wennen. - - Overigens, omdat ik juist 'left' en 'right' heel vaak moest - gebruiken, heb ik de volgende twee #defines gemaakt: - - #define NLEFT nodeinfo.ptrnode.left - #define NRIGHT nodeinfo.ptrnode.right - - Dat voorkomt kramp in de typevingers. - - - N I E U W E T Y P E N D E F I N I E R E N - - In het geval van structs en unions kunnen we een eenmaal - gedefinieerd type telkens opnieuw gebruiken, als we er maar - voor zorgen dat we het een 'tag name' hebben gegeven. Bij - arrays of ingewikkelde pointer types, of erger nog: - combinaties ervan, zou het handig zijn (en fouten voorkomen) - als we het type slechts een keer moesten definieren. Dat kan - met een zogenaamde 'typedef'. - - Het gebruik van 'typedef' is heel eenvoudig. Als je uitgaat - van de declaratie van de variabele van het gewenste type, - volstaat het om er het woordje 'typedef' voor te zetten, en - de naam van de variabele te vervangen door de naam die je - het nieuwe type wilt geven. - - Als je bijvoorbeeld een type LONG wilt maken (omdat je - compiler - zucht - geen long's kent) kun je bijvoorbeeld als - volgt te werk gaan: - - typedef char LONG[4]; - - Een LONG is dan gedefinieerd als een array van 4 char's, en - kan nu in declaraties worden gebruikt, zoals: - - LONG lang_getal1, lang_getal2; - - Natuurlijk heft dat geen van de beperkingen op die voor het - specifieke datatype gelden en dus zal bijvoorbeeld - - lang_getal1 = lang_getal2; - - tot een foutmelding leiden, zoiets als "must be lvalue", - omdat we hier in feite arraynamen, en dus pointerconstanten, - gebruiken! (Dat heeft weer wel als voordeel dat we bij ons - nieuwe type deze arraynaam zonder meer als parameter aan - functies kunnen doorgeven, zonder dat we specifiek het adres - hadden moeten doorgeven; alles heeft voor- en nadelen.) - - - Het volgende tekstdeel kunt u in het submenu vinden - - - - - - Het eerste tekstdeel kunt u in het submenu vinden - - - D E P R O G R A M M E E R T A A L C - - D E E L 5 - - - - G E H E U G E N B E H E E R I N C - - PASCAL programmeurs zullen zich bij al die pointers wel even - het hoofd hebben geschud. Immers, de enige manier waarop zij - met pointers kunnen werken is na een NEW, die een nieuwe, - anonieme variabele cre�ert, en een pointer ernaar - teruggeeft. Dat is (officieel) de enige manier waarop je in - PASCAL aan een pointer kunt komen. - - Deze beperkingen zijn waarschijnlijk opzettelijk, omdat - pointers tevens een belangrijke bron van fouten zijn. Zelfs - binnen het keurslijf van PASCAL kunnen pointers naar - niet-meer-bestaande objecten overblijven na een MARK/RELEASE - of DISPOSE. - - Toch is de keuze die men voor PASCAL gemaakt heeft zo gek - nog niet: bij anonieme variabelen moet je immers wel met - pointers werken, omdat je er niet bij naam naar kan - verwijzen, en bij veel algorithmen die gebruik maken van - bomen ('trees') en lijsten ('linked lists') - en dus - pointers - moet je nieuwe objecten kunnen cre�ren en oude - vernietigen. Vandaar dat men die link (woordspeling - opzettelijk!) tussen geheugenbeheer en pointergebruik legde. - - Inderdaad, geheugenbeheer. Voor wie het nog niet door had: - als je een nieuwe variablele wilt cre�ren dan heb je - (ongebruikt) geheugen nodig, en dat geheugen moet ergens - vandaan komen. In C zijn daar verschillende manieren voor, - de meest gebruikelijke zijn echter: - - calloc(aantal, grootte) - malloc(grootte) - alloc(grootte) - - De functie 'calloc' reserveert geheugen voor 'aantal' - objecten van 'grootte' bytes, 'malloc' en 'alloc' een blok - van 'grootte' bytes. Deze twee laatste doen dus precies - hetzelfde, tenminste op byte-georienteerde systemen zoals de - Z80. Alle parameters van alledrie de functies zijn unsigned, - en alledrie geven ze een char * terug naar het eerste byte - in het blok geheugen, of NULL als er onvoldoende geheugen - beschikbaar is. - - In tegenstelling tot PASCAL kunnen we dus niet direct een - bepaald object cre�ren, we zijn er zelf verantwoordelijk - voor om de juiste hoeveelheid geheugen te reserveren. - Gelukkig is dat niet zo moeilijk. Willen we bijvoorbeeld een - nieuw object van het type 'struct name' (zie eerder) dan kan - dat met - - malloc(sizeof(struct name)) - - en bij wat strengere compilers moeten we bovendien casts - gebruiken, en dan wordt het bovenstaande: - - (struct name *)malloc((unsigned)sizeof(struct name)) - - Dat ziet er lelijk - en onbegrijpelijk - uit. Zo'n - wanproduct kunnen we binnen een aparte functie plaatsen (wat - we kunnen combineren met een actie wanneer er onvoldoende - geheugen beschikbaar is) zoals: - - struct name *newname() - { - char *temp; - - if ((temp = malloc((unsigned)sizeof(struct name))) == - NULL) { fputs("Onvoldoende geheugen!\n", stderr); - exit(1); } /* einde programma! */ - - return (struct name *)temp; - } - - Als onze preprocessor voldoende krachtig is, en ook - #define's met parameters accepteert (zoals ASCII-C) kunnen - we ook het volgende doen: - - #define NEW(x) (((x) *)malloc((unsigned)sizeof(x))) - - en dan reserveren we altijd de juiste hoeveelheid geheugen - en krijgen we altijd het juiste type pointer terug, wat voor - data-type we ook voor x invullen. Nu kunnen we eenvoudig "a - la PASCAL" - - NEW(struct name) - - doen. Et voila! Deze manier is heel efficient, vooral omdat - het ons geen byte aan code extra kost: al die casts zijn er - tenslotte voor de interne administratie van de compiler. - - Omdat 'calloc(aantal, grootte') precies hetzelfde doet als - 'malloc(aantal * grootte)' zal 'calloc' hier wel geen - verdere toelichting behoeven. Waar in de rest van het - verhaal 'malloc' staat kan dus ook - mutatis mutandis - - 'calloc' of 'alloc' worden gelezen. - - Het geheugen dat we met een van bovenstaande functies hebben - gekregen kunnen we ook aan het systeem teruggeven, waarna - het weer voor beschikbaar wordt voor een volgende 'malloc', - 'alloc' of 'calloc'. Hiervoor is de functie - - free(pointer) - - beschikbaar. De parameter 'pointer' is een char * en we - moeten hier dezelfde pointer gebruiken die we via 'malloc' - e.d. hebben gekregen. De functie 'free' geeft geen waarde - terug. - - Meer voor de volledigheid dan om praktische redenen wil ik - hier nog vermelden dat C nog een functie heeft om geheugen - te reserveren, namelijk 'sbrk'. Niet alle C-compilers - ondersteunen deze functie, en bovendien kan met deze functie - gereserveerd geheugen niet terug worden gegeven aan het - systeem. Wederom een Unix-relikwie. - - Ook kent C nog een paar, weinig gebruikte functies om - blokken geheugen te verplaatsen of te vullen. Deze zijn: - - memcpy(dst, src, len) - movmem(src, dst, len) - memset(dst, byte, len) - setmem(dst, len, byte) - - De functies 'memcpy' en 'movmem' verplaatsen een blok - geheugen dat 'len' bytes groot is van 'src' naar 'dst' - ('len' is unsigned, 'dst' en 'src' zijn char *). Deze - functies zijn identiek, op de volgorde van de argumenten na. - Overigens mogen de 'src' en 'dst' gebieden niet overlappen. - De functies 'memset' en 'setmem' vullen een geheugengebied - vanaf 'dst', dat 'len' bytes groot, is met de waarde 'byte', - een char. Ook bij deze twee functies is alleen de volgorde - van de argumenten verschillend. Aangezien het ANSI comite - aan de functies 'memcpy' en 'memset' de voorkeur geeft is - het misschien verstandig dit zelf ook te doen. - - - S T R A T E G I E E N V A N G E H E U G E N - - - B E H E E R : E E N V E R G E L I J K I N G - - Vooral assemblyprogrammeurs zullen bij bovenstaand verhaal - de oren hebben gespitst en denken: "maar zijn er dan geen - restricties in de volgorde waarin geheugen wordt aangevraagd - en teruggegeven, en moet bij 'free' niet de grootte van het - blok geheugenblok worden vermeld?" Op beide vragen luidt het - antwoord: nee! Het geheugenbeheersysteem van C is erg - flexibel wat dat betreft, maar voor alles moet een prijs - worden betaald. - - In de eerste plaats moet het systeem zelf bijhouden hoeveel - geheugen er in een blok zit. De meestgebruikte manier omdat - te doen is de grootte van een blok direct voor dat blok op - te slaan, wat op zich al wat geheugen kost. - - In de tweede plaats moet een blok een bepaalde minimale - grootte hebben, of soms zelfs een veelvoud van een bepaalde - waarde, omdat er zelfs in een ongebruikt geheugenblok nog - bepaalde informatie moet worden opgeslagen. Deze twee feiten - maken het onaantrekkelijk om zeer veel kleine blokken te - gebruiken, omdat anders het verlies erg groot wordt. In zo'n - geval kan het aantrekkelijk zijn een of meer grote blokken - geheugen aan te vragen, en daar zelf een beheerstrategie - voor uit te denken. Vooral als we met stukjes geheugen van - allemaal gelijk formaat willen werken kan dit vaak heel - eenvoudig. - - Als laatste probleem wil ik noemen het (mogelijk) - versnipperen van het geheugen in allemaal kleine blokken, - wat tot gevolg kan hebben dat er geen blokken geheugen van - een bepaalde minimale grootte meer beschikbaar zijn, hoewel - de totale hoeveelheid vrij geheugen ruim voldoende kan zijn. - Een en ander hangt af van in welke volgorde we de blokken - aanvragen en weer vrijmaken, en hoe het formaat van de - verschillende blokken uiteenloopt. In de praktijk valt het - echter allemaal wel mee. - - Als vergelijking wil ik hier noemen de manier waarop BASIC - met strings omgaat. Strings in BASIC zijn variabel van - lengte, en voor een string kan dus geen vaste hoeveelheid - geheugen worden gereserveerd. Maar de geheugenallocatie voor - strings wordt veel simpeler aangepakt, en geheugen wordt ook - niet expliciet weer vrijgegeven. Als gevolg daarvan is het - geheugen dan ook vrij snel vol, en vervolgens gaat de - interpreter een zogenaamde 'garbage collection' uitvoeren, - die uiteindelijk tot gevolg heeft dat alle bezette delen - achterelkaar worden geplaatst, en er een enkel vrij blok - geheugen ontstaat. - - Dit klinkt op het eerste gezicht aantrekkelijk, maar er zijn - een paar problemen. Het belangrijkste is wel dat de - informatie verschuift, en alle pointers naar die informatie - aangepast moeten worden. In BASIC gaat dat nog wel, omdat de - interpreter het beheer over die pointers (lees: string - descriptors) voert, en precies weet waar ze zich bevinden. - In C is dit niet mogelijk, omdat de pointers (en mogelijke - kopieen daarvan) over het gehele geheugen verspreid kunnen - zijn, vaak in de geheugenblokken zelf! - - Dat zo'n garbage collection ook nog eens bijzonder traag - gaat is de BASIC programmeur wel bekend, hoewel dat laatste - voor een niet onbelangrijk deel aan de 'gierigheid' van de - BASIC-interpreter ligt: als ze twee bytes extra per string - hadden geinvesteerd hadden ze de garbage collection een orde - sneller kunnen maken, en hadden bovendien niet alle string - descriptors in hetzelfde geheugendeel hoeven liggen. Ik - spreek hier uit ervaring, want ik heb zelf eens een - stringuitbreiding voor FORTH geprogrammeerd, en ik heb het - systeem nooit zichtbaar zien vertragen tijdens een garbage - collection. - - Maar het feit dat de informatie in zo'n systeem van plaats - kan veranderen kan in veel gevallen toch tot problemen - leiden, en vraagt de nodige discipline van de gebruiker. In - bovenstaand FORTH systeem worden strings dan ook in een keer - naar de stack gekopieerd voor ermee gewerkt mag worden, en - ook weer in een keer weggeschreven, en dat maakt een en - ander toch weer wat minder efficient. (Al past deze - werkwijze wel bij uitstek in de FORTH-filosofie!) - - Binnen TURBO PASCAL kan op ongeveer dezelfde manier worden - gewerkt als in C met NEW/DISPOSE of GETMEM/FREEMEM, al moet - bij FREEMEM in tegenstelling tot C wel de grootte van het - geheugenblok worden opgegeven. Binnen TURBO PASCAL kan - echter ook met MARK/RELEASE worden gewerkt (maar dan niet - met DISPOSE of FREEMEM!) om alle blokken die aangevraagd - zijn na een bepaald eerder blok weer vrij te geven. Een en - ander functioneert dan ongeveer als een stack. C - programmeurs die hetzelfde willen kunnen doen moeten daar - zelf een routine voor schrijven, die echter bijzonder simpel - is als we in een enkel, aaneengesloten blok geheugen werken. - - - - I N I T I A L I Z E R S - - Een van de meestgebruikte statements in BASIC is 'DATA'. Er - zijn nauwelijks programma's van enige omvang die niet zijn - gezegend(?!) met een grote hoeveelheid van deze dingen, - meestal aan het eind. Zelfs als we die DATA's niet - meerekenen die gebruikt zijn om een stukje machinetaal in te - zetten - omdat het programma anders niet vooruit te branden - is - blijkt dat we er nog een hoop overhouden met tabellen - en dergelijke. - - Handige programmeurs maken vaak gebruik van tabellen, omdat - het programma er vaak een stuk simpeler en kleiner van - wordt. Ook op dit gebied laat C niemand in de steek, omdat - we al onze variabelen mogen intialiseren met een waarde of - waarden bij de declaratie ervan. Dit kan met een simpele - variabele als volgt: - - int var1 = 0; - char var2 = 'N'; - unsigned var3 = 5 * 4; - char *var4 = "En dit is ook een constante!"; - - We mogen variabelen alleen initialiseren met constanten, of - constante uitdrukkingen. Samengestelde typen mogen echter - alleen initialiseren als het statische variabelen zijn - (buiten een functie is dat altijd zo). Voor automatische - variabelen (die komen alleen binnen een functie voor) gelden - dezelfde beperkingen als die voor een assignment. (In feite - wordt het ook naar een assignment vertaald, wat logisch is: - bij het aanroepen van de functie moet de initialisa- - tie telkens opnieuw plaatsvinden!) - - In het het laatste voorbeeld van bovenstaand rijtje moeten - we ons realiseren dat we een pointer variabele initialiseren - zodat hij naar die string wijst; de string zelf zit op een - andere plaats in het geheugen. Doen we echter dit: - - char var4[] = "En nu vullen we een array!"; - - Dan wordt var4 een array, en gevuld met boventaande string. - Deze methode is wat efficienter want we sparen een pointer - variabele uit. We hoeven ook niet op te geven hoe groot het - array moet worden, want dat is gewoon de lengte van de - string met afsluitende nul: dat zoekt de compiler zelf wel - uit. - - Een string kan dus twee betekenissen hebben in een - initializer. De tweede manier gebruikt de string als een - blok gegevens, maar dit kan ook door een aantal constanten, - of constante uitdrukkingen, gescheiden door komma's, tussen - accoladen te zetten. De volgende twee declaraties zijn dan - ook volledig identiek: - - char str[] = "String"; - char str[] = { 'S', 't', 'r', 'i', 'n', 'g', 0 }; - - In het algemeen is de eerste vorm wat duidelijker, maar die - kunnen we natuurlijk alleen gebruiken als het om strings - gaat. In alle andere gevallen en bij alle samengestelde - typen moeten we van dit soort gegevensblokken tussen - accoladen gebruiken. In het geval we samengestelde typen - binnen samengestelde typen gebruiken moeten we zelfs - gegevensblokken binnen gegegevensblokken gebruiken. We - moeten zo'n blok dus eigenlijk zien als een samengestelde - constante. Hier een aantal voorbeelden: - - int rij[] = { 1, 2, 3 }; - int matrix[][] = { { 1, 2, 3 }, { 4, 5, 6 }, - { 7, 8, 9 } }; - struct point pnt3 = { 0, 1, -1 }; - struct point vlak[] = { { 1, 0, 0 }, { 0, 1, 0 }, - { 0, 0, 1} }; - char *teksten[] = { "tekst1", "tekst2", "tekst3", - "tekst4" }; - - - In het laatste geval hebben we een array van char pointers - gemaakt, en elk van die pointers wijst naar een van de - teksten. Verder nog vragen? Geen vragen! En dus wordt dit - het einde van deze aflevering! - - Robert Amesz - - - P.S.: Het zal misschien een aantal mensen opgevallen zijn - dat een voorbeeldprogramma deze aflevering ontbreekt. Sorry. - Dat komt pas bij aflevering 6, wanneer het over zulke - diverse onderwerpen zal gaan als modulair programmeren, het - maken van functiebibliotheken, debuggen, combineren met - machinetaal, enz. enz. diff --git a/sunrise_special/4/Easy BDOS.md b/sunrise_special/4/Easy BDOS.md deleted file mode 100644 index b577f7a..0000000 --- a/sunrise_special/4/Easy BDOS.md +++ /dev/null @@ -1,403 +0,0 @@ - E A S Y B D O S - - - Opm: Ik ga er in dit artikel van uit dat de lezer een - behoorlijke kennis van de BDOS bezit. - - Het aansturen van een diskdrive is een zeer lastig - karweitje. Zelfs ervaren programmeurs zullen meerdere malen - verwensingen aan bepaalde chipfabrikanten maken tijdens het - schrijven van software om een FDC (Floppy Diskdrive - Controller) aan te sturen. Dat is ��n van de redenen waarom - de BDOS standaard in MSX zit. De BDOS maakt elke kennis van - FDC's overbodig voor het aansturen van een diskdrive. De - BDOS software schept als het ware een interface van en naar - de gebruiker dat vele malen eenvoudiger is dan het direkt - aansturen van de FDC. (Nvdr: en het werkt ook nog op bijna - alle computers.) - - We zijn de ontwerpers van de BDOS dan ook eeuwig dankbaar - voor deze vriendelijke geste, maar er schort nog het ��n en - ander aan dit 'gebruikersvriendelijke' interface. Het - schrijven van een goede routine om een file van disk te - laden is nl. niet zo eenvoudig als de BDOS doet vermoeden. - Om dit te bewijzen zal ik eerst maar een voorbeeld geven van - de meest eenvoudige methode om een file te laden. - - Stel we willen een MoonBlaster muziekstuk inladen. Een - dergelijke file is praktisch altijd kleiner dan 16 kB. Met - deze kennis kan dan de volgende routine geschreven worden. - - LD_MBM: LD C,15 - LD DE,FCB - CALL &HF37D ; Open file om eruit te lezen - INC A ; If A=255, then error - JR Z,NO_OK ; Fout tijdens openen file - LD HL,0 - LD (FCB+12),HL ; Zet start(lees)blok op 0 - INC HL - LD (FCB+14),HL ; Zet recordlengte op 1 - LD C,26 - LD DE,MUSADR - CALL &HF37D ; Leesadres van file is MUSADR - LD C,39 - LD DE,FCB - LD HL,&H4000 ; Lees max. 16kB - CALL &HF37D ; Lees blok - DEC A ; A=1, then error - JR NZ,NO_OK - OK: : - : - RET - - NO_OK: : - : - RET - - FCB: DB 0 - DM "MB_MUSIC","MBM" - DW 0,0 - DW 0,0,0,0,0,0,0,0 - DW 0,0 - DB 0 - - Na de bestudering van dit 'programma' valt de - foutafhandeling van de feitelijke laadaktie (C=39) op. - Indien de BDOS hier een foutmelding geeft is de laadaktie - goed? Dit komt omdat we probeerden 16 kB in te laden terwijl - we weten dat de file per definitie kleiner dan 16kB is. - Zelfs de BDOS zal niet voorbij het eind van een file - proberen te lezen en geeft dientengevolge een foutmelding. - - Deze routine rammelt werkelijk aan alle kanten en kan veel - beter geschreven worden. Dit kan door de recordlengte gelijk - te maken aan de bestandslengte. Na het openen van de file - staat de bestandslengte in het FCB. Door deze in de - recordlengte te kopi�ren en daarna bij de laadaktie niet - 16 kB in te lezen, maar 1 record gaat het wel goed. - - Dit soort routines heeft verder als nadeel dat ze absoluut - niet universeel inzetbaar zijn. Voor het laden van muziek en - andere data gaat het wel, maar om graphics behoorlijk te - laden moet meer uit de kast gehaald worden. Het zou er op - neerkomen dat er voor elke soort te laden file een aparte - routine zou moeten komen met eigen error handling. U - begrijpt, dit levert enorme listings op met routines die - toch heel erg veel op elkaar lijken. - - Wat ik hiermee probeer aan te tonen is dat de BDOS een - uiterst noodzakelijk stukje software is, maar dat er bij het - gebruik toch nog wat haken en ogen aan zitten. Naast de - normale BDOS error handling (BDOS uitvoer via het A - register) is er nl. ook nog de error pointer hook die bij - ernstige diskdrive fouten aangeroepen wordt. Probeer maar - eens een file te cre�ren met de diskdrive protect schuif - open. Uw machinetaal programma zal zonder pardon naar BASIC - terugkeren (een verbijsterde programmeur achterlatend). - - - K A N H E T E E N V O U D I G E R ? - - Natuurlijk, is dan mijn antwoord. Praktisch is gebleken dat - het goede gebruik van de BDOS helemaal niet zo eenvoudig is - als de makers doen geloven. Wat we nodig hebben is software - die een nieuw interface tussen de diskdrive en de gebruiker - vormt waardoor de gebruiker absoluut geen kennis van de BDOS - meer nodig heeft. Het enige waar de gebruiker zich nog om - hoeft te bekommeren is dat hij ervoor moet zorgen dat de - gegevens op de juiste plaats terecht komen. - - Laten we eerst maar eens gaan kijken wat deze software moet - doen. Praktisch blijkt dat 95% van alle BDOS gebruik beperkt - blijft tot het laden of bewaren van gegevens. Het heeft - praktisch dus ook weinig zin om onze nieuwe besturings - software iets anders te kunnen laten doen. - - Foutmeldings uitvoer van de routines kan beter met de Cy - flag gedaan worden dan met het A register (zoals de BDOS - doet). Dit komt omdat via de Cy flag onmiddelijk een - spronginstruktie gedaan kan worden terwijl met het A - register eerst een flag zet instruktie gedaan moet worden. - - - E A S Y B D O S F U N C T I E S - - De nu te beschrijven routines zijn terug te vinden in de - file EASYBDOS.ASC die op deze disk te vinden is. De - verzameling routines heet de fileshell omdat ze nl. als een - schil om de BDOS heen zitten. - - De routines laten nog te wensen over. Zo kan er maar 1 file - tegelijkertijd open staan, terwijl de BDOS er veel meer kan - hebben. Het toevoegen van een dergelijke optie zou voor de - gemiddelde programmeur echter weinig problemen op moeten - leveren. Ik kan me voorstellen dat FOPEN en FCREAT een - nummer in het A register teruggeven die dan bij resp. FBLKRD - en FBLKWR weer meegegeven moeten worden. Elk nummer staat - dan voor een bepaald FCB waarvan het adres dan wel door de - routines berekent kan worden. Let er daarbij wel op dat de - variabele FSTAT dan niet meer naar behoren funktioneert, dus - ook dit moet dan aangepast worden. - - Een andere beperking is die dat de maximale lengte van een - te lezen file 65535 bytes is. Deze beperking is echter - redelijk eenvoudig op te lossen. Het gebruik van deze - routines is in eerste instantie ook alleen maar bedoeld voor - demo's en kleine utilities. Voor het wat serieuzere werk zal - ik deze twee beperkingen er nog wel eens uit halen. - - - F I L E S H E L L I N S T A L L - Name: FINSTL - In : A, (see BIOS routine &H24) - Out : Cy, on error - - Deze routine installeert de software. Naast het - initialiseren van enkele systeemvariabelen buigt deze - routine de BDOS pointer error hook af zodat bij een ernstige - fout niet meteen naar BASIC gesprongen wordt. Elke aanroep - die vanaf nu rechtstreeks naar de BDOS gemaakt wordt, zal - afgevangen worden zodat de error handling ook dan actief is. - A moet bij invoer de slot en subslot waarden van page 1 - bevatten. Het programma zou dit ook zelf wel uit kunnen - zoeken, maar dat gaat hier wat ver. - - Heb je bv. de BASIC ROM nog 'aan' staan, dan is de aanroep - als volgt: - - LD A,(&HFCC1) ; Slot en subslot van MAIN-ROM - CALL FINSTL - RET C ; Error - - Is de BASIC ROM vervangen door RAM geheugen, dan is de - aanroep: - - LD A,(&HF342) ; Slot en subslot van MAIN-RAM - CALL FINSTL - RET C - - Indien FINSTL niet uitgevoerd wordt zal elke andere - fileshell routine aanroep onmiddelijk een foutmelding terug - geven. - - - F I L E S H E L L R E S E T - Name: FRESET - In : nothing - Out : Cy, on error - - Met FRESET kan de fileshell software weer van de BDOS - verwijderd worden. De BDOS wordt niet langer afgetapt en - error handling wordt niet meer gedaan. Indien er nog een - schrijf file open staat wordt deze eerst automatisch - gesloten. - - - O P E N F I L E - Name: FOPEN - In : HL, filename address - OUt: Cy, on error - - FOPEN moet aangeroepen worden wanneer een file gelezen moet - worden (net als bij de BDOS overigens). HL moet bij invoer - wijzen naar de filenaam. Dit ziet er als volgt uit: - - LD HL,MBMNME - CALL FOPEN - RET C - : - : - - MBMNME: DM "MB_MUSIC","MBM" - - De filenaam MOET 11 karakters lang zijn. Indien de naam niet - 8 karakters lang is moet de naam met spaties aangevuld - worden. Ditzelfde geldt ook voor de extensie. - - - F I L E B L O C K R E A D - Name: FBLKRD - In : DE, blocklength - HL, load address - Out : Cy, on error - A , ="r" if file is loaded. - - FBLKRD leest een blok van een geopende file. Indien de - blocklengte groter is dan de (resterende) filelengte past de - routine deze automatisch aan. HL mag alle waarden hebben - behalve het adresgebied tussen &H4000 en &H8000 (page 1). - Deze beperking wordt door het MSX systeem opgelegt. Sommige - programmeurs schijnen dit nog steeds niet te weten. Indien - de file helemaal geladen is staat bij uitvoer het karakter - "r" in register A (De r van 'ready'). Willen we nu een file - laden die groter is dan 16 kB in blokken van 16 kB dan gaat - dat bv. als volgt: - - LD A,1 - LOOP: OUT (&HFE),A ; Zet memory mapper - PUSH AF - LD DE,&H4000 ; Lees max. 16kB blok - LD HL,&H8000 ; Vanaf adres &H8000 - CALL FBLKRD - EX AF,AF ; Bewaar uitvoer - POP AF - INC A ; Volgende memory map. pagina - EX AF,AF ; Haal uitvoer weer op - RET C ; Error - CP "r" ; Klaar met laden - RET Z - EX AF,AF - JR LOOP - - - C R E A T E F I L E - Name: FCREAT - In : HL, filename address (See FOPEN) - Out : Cy, on error - - Met FCREAT kan een nieuwe file gemaakt worden (net als bij - de BDOS). - - - F I L E B L O C K W R I T E - Name: FBLKWR - In : DE, blocklength - HL, startaddress - Out : Cy, on error - - Deze routine werkt in principe net zo als de block laad - routine, met het verschil dat de file automatisch gesloten - wordt na het optreden van een foutmelding. - - LD DE,&H1000 ; Schrijf 4kB - LD HL,&H8000 ; Vanaf adres &H8000 - CALL FBLKWR - RET C ; Fout opgetreden - LD DE,&H1000 - LD HL,&HB000 - CALL FBLKWR - RET C - CALL FCLOSE ; Sluit file indien klaar - XOR A ; Maak Cy laag - RET - - - C L O S E F I L E - Name: FCLOSE - In : Nothing - Out : Nothing - - Deze routine doet niets meer dan het aanroepen van het BDOS - close commando en is nodig om een net aangemaakte file af te - sluiten. - - - C H A N G E D I S C - Name: CHNDSK - In : A - Out : Nothing - - Change disk is een extraatje. Indien A bij aanroep 0 is - wordt de boodschap "Insert source disk" op het scherm gezet - en in alle andere gevallen "Insert destination disk". Daarna - wordt gewacht tot de spatiebalk ingedrukt wordt. Indien twee - keer achter elkaar een source disk aangevraagd wordt zal de - routine meteen terug springen zonder een tekst op het scherm - te zetten. - - - De nu volgende routines zijn niet voor de gebruiker bedoeld, - maar ik noem ze toch maar even. - - INTOFF: - Deze routine zet de VDP interrupt (50/60 Hz) generator uit. - Hierdoor gaat het laden (vooral op trage Sony's) sneller. - - INTON: - Laat zich raden. - - FBDOS: - Dit is de routine waar elke BDOS aanroep na aanroep van - FINSTL naar toe springt. - - ERRCDE: - Dit is de routine waar naartoe gesprongen wordt bij een BDOS - error handling via de pointer hook. Deze routine heeft een - 'Abort, Retry' optie ingebouwd en voorkomt dat bij een - dergelijke fout naar BASIC gesprongen wordt. De routine - wordt bv. aangeroepen wanneer de disk uit de drive gehaald - wordt tijdens bv. een laadaktie. - - !!! WAARSCHUWING !!! - - Net als enkele belankrijke variabelen (vanaf PG1SET) mag - deze routine niet op page 1 gemapt worden. Zet deze routine - bij voorkeur op page 3 (vanaf &HC000). - - Bij een abort wordt de stack hersteld en worden de slot en - subslot instellingen van page 1 hersteld naar de waarde die - bij FINSTL opgegeven is. Dit moet omdat de BDOS ROM zich nl. - op PAGE 1 nesteld tijdens disk akties. Hierna wordt de stack - hersteld en geeft de routine een standaard BDOS error terug - (A=1). Met deze methode wordt terugspringen naar BASIC - voorkomen. - - Bij een Retry wordt het C register 1 gemaakt waardoor de - BDOS de disk aktie zal proberen te herhalen! - - PRTERR: - Deze routine wordt gebruikt door alle fileshell routines om - foutmeldingen op het scherm te zetten. Invoer gaat via het A - register waar het foutnummer in staat. Deze methode zorgt - ervoor dat de feitelijke fileshell routines korter en - overzichtelijker worden. - - - Als laatste zijn er dan nog de fileshell variabelen. - Vanaf PG1SET mogen de variabelen niet meer op PAGE 1 gemapt - zijn. Zet deze dus het liefst vanaf adres &HC000. - - FSTAT: - Hierin staat de fileshell status. De opbouw is als volgt: - Bit 0, hoog, dan is FINSTL uitgevoerd (fileshell aktief) - Bit 1, hoog, dan is de huidige file open voor lezen - Bit 2, hoog, dan is de huidige file open voor schrijven - (Bit 1 en 2 kunnen dus nooit gelijktijdig hoog zijn) - - CURDRV: - Huidige drive. - 255, dan is CHNDSK nog nooit aangeroepen - 0 , dan is de huidige disk de 'source disc' - 1 , dan is de huidige disk de 'desination disc' - - FLELEN: - Het aantal nog te LEZEN bytes van een open file. - - _##ERR: - Bewaarplaats van de oude BDOS error double pointer - - OLDDOS: - Bewaarplaats van oude BDOS aanroep hook - - PG1SET: - Bewaarplaats van bij FINSTL opgegeven slot instellingen - - SP_SAV: - Bewaarplaats voor StackPointer register - - FCB: - Het FCB - - - Dat is het dan. Probeer de listing eens uit. De minste - problemen zullen optreden als de complete listing vanaf - &HC000 begint. Lees ook eens het artikel over de BDOS error - handling om wat gedetailleerdere informatie te krijgen. Ik - zou zeggen, klieder naar hartelust in het gegeven - programmeervoer en haal de twee eerder genoemde beperkingen - er zelf eens uit. Let vooral op hoe snel het met deze - routines mogelijk is om complete laad of save routines in - elkaar te gooien en hoe klein deze dan zijn. Tot de volgende - preek. - - Alex van der Wal diff --git a/sunrise_special/4/GetDisk 2.0.md b/sunrise_special/4/GetDisk 2.0.md deleted file mode 100644 index d6f383f..0000000 --- a/sunrise_special/4/GetDisk 2.0.md +++ /dev/null @@ -1,126 +0,0 @@ - G E T D I S K 2 . 0 - - - Op deze Sunrise Special staan de nieuwe versies van de - harddisk utility's die op de vorige SRS hebben gestaan. Met - deze programma's kan een spel dat een (of meer!) hele - diskette(s) beslaat als een file op de harddisk worden - opgeslagen en worden opgestart. - - - A A N P A S S I N G E N - - Ik heb de programma's geheel herschreven en nu gebruik - gemaakt van DOS2 system calls. Hierdoor is de snelheid - verbeterd, maar het werkt nu natuurlijk niet meer onder - DOS1, maar harddiskgebruikers onder DOS1 kunnen natuurlijk - nog gewoon de oude versie blijven gebruiken. Maar een - harddisk onder DOS1 is als een normaal mens achter een - Amiga; er zullen wel niet veel DOS1 HD gebruikers meer zijn. - - - V E R D E R E V E R A N D E R I N G E N - - Het gedeelte dat de diskette inleest en op de harddisk zet - is nu gecombineerd tot de COM-file GETDISK.COM i.p.v. - GETDISK.BAS en GETDISK.BIN. - - Bij het opstarten van GETDISK.COM wordt er eerst gevraagd - van welke drive de diskette ingelezen moet worden. Daarna - wordt om het aantal diskettes gevraagd en als laatste onder - welke naam de file bewaard moet worden. - - Bij zowel GETDISK.COM als START.COM kan er nu een path - worden opgegeven. START.COM handelt nu de phydio BIOS call - beter af, waardoor meer spellen onder DOS2 draaien. - - Als laatste is er een programma ADAPT.COM bij gekomen dat - een bestand dat al is opgeslagen met GETDISK.COM langsloopt - om te kijken of de diskrom soms rechtstreeks wordt - aangeroepen en zonodig deze calls verandert. Gebruik - ADAPT.COM alleen als een spel niet met START.COM opgestart - kan worden, zoals bij de spellen van Bit2. - - - A L L E S O P E E N R I J T J E - - - Start het programma GETDISK.COM op (zonder parameters) en - geef op welke driveletter de diskdrive heeft. - - Tel nu hoeveel diskettes het spel is dat op harddisk gezet - moet worden (vergeet niet de evt. userdisk mee te - rekenen). - - Geef dit aantal op en geef de naam (met evt. drive en - path) op waaronder het spel bewaard moet worden. - - Probeer het spel op te starten met START - drive:\path\filename.ext. - - Loopt de computer vast, reset dan en probeer ADAPT - drive:\path\filename.ext - - Start het spel nog een keer op met START.COM - - Werkt het nu nog steeds niet, dan kan het spel helaas - (nog) niet op de harddisk. - - - D E S P E L L E N - - De spellen in dit lijstje werken met GETDISK. Als je nog een - spel gevonden hebt, kun je dat laten weten via Sunrise BBS - Nuth of de postbus, t.a.v. Kasper Souren. - - Compile: Aleste Special - Golvellius 2 - Gorby's Pipeline - Nyanpi - Puyo Puyo - Randar 3 - Rune Master 1 - Rune Master 2 - Rune Master 3 - Supercooks - Konami: F1-Spirit 3D - Momonoki house: Peach Up summary 2 - Peach Up 8 - DBP: Tetris - Falcom: Ys 3 - Bit2: Quinpl (ADAPT.COM gebruiken) - Nyancle (ADAPT) - Wolfteam: Niko Niko - ?: Herzog - ?: Haradius - ?: Pacmania - - - Het moge duidelijk zijn dat al deze spellen onbeveiligd - zijn. Dat wil zeggen: ze moeten met FastCopy te kopi�ren - zijn door gewoon track 0 t/m 79 te kopi�ren. - - Van Compile werkt tot nu toe alleen Aleste 2 niet. Ik - vermoed dat ook alle DiscStations en Randar 1 en 2 goed - zullen functioneren. - - Ik vermoed dat Ys 1 en Ys 2 ook werken, maar dit kan ik niet - controleren omdat ik deze spellen niet bezit. - - Noot: alleen spellen die helemaal op sector staan werken. - Spellen die niet alleen op sector staan, maar ook files - laden, kunnen niet met de huidige versie van GETDISK worden - gebruikt. Hierdoor vallen helaas alle MicroCabins weg. - - - PUTDISK - - Op deze Special staat ook PUTDISK.COM. Hiermee kun je een - spel weer terug op diskettes zetten. Handig als je even de - userdisk nodig hebt om ergens anders te spelen. - - - R800 - - Spellen die de MSX-MUSIC chip rechtstreeks aansturen zullen - geen rekening hebben gehouden met de R800. Daarom is het - geluid verminkt als het spel onder R800 gedraaid wordt. - Spellen die alleen de PSG gebruiken (Ys 3, Herzog) werken - wel goed. Ook zijn er spellen die de FM BIOS gebruiken, - bijv. Pacmania, en die werken dan wel goed. - - Michel Shuqair - Kasper Souren diff --git a/sunrise_special/4/HD Indelen.md b/sunrise_special/4/HD Indelen.md deleted file mode 100644 index b4ae85b..0000000 --- a/sunrise_special/4/HD Indelen.md +++ /dev/null @@ -1,110 +0,0 @@ - H D I N D E L E N - - - Het indelen van een harddisk kan natuurlijk heel snel - gebeuren. Maar het is verstandiger om even erover na te - denken. Er bestaat nl. de kans dat je veel files niet meer - kunt vinden na verloop van tijd, als je gewoon lukraak - subdirectory's aanmaakt. - - Dat er dan een programma als FileFind bestaat, doet daar - niks aan af. Het is onhandig om telkens als je iets nodig - hebt weer FF te moeten gebruiken. - - Ook kun je denken aan welke schil je wilt gebruiken. Gewoon - onder MSX-DOS werken met een paar batchfiles of een GUI - (Graphical User Interface) als MSX-View of Easy. - - - P A R T I T I E S - - Om te beginnen bij het begin: je moet de harddisk opdelen in - partities (high level formatteren genaamd; meestal is de - harddisk al low level geformatteerd). Je kunt, als je een - harddisk kleiner dan of gelijk aan 32 MB hebt, gewoon ��n - partitie aanmaken. Maar dit is niet erg slim. Je krijgt dan - vrij grote clusters, soms zelfs van 32 kB. Hierdoor wordt je - harddisk niet erg snel. - - Het is dus verstandig om een kleine A: partitie aan te maken - met daarop allerlei programma's (aatjes) die je vaak - gebruikt. Ikzelf heb gekozen voor 4 MB. Als je dan de FAT op - 12 sectoren zet, heb je clusters van 1 kB. - - - F A T G R O O T T E - - Je kunt het beste altijd een FAT van 12 sectoren nemen, dan - is de clustergrootte het kleinst. Dit komt ook weer de - snelheid ten goede. Maar niet alleen de snelheid. Bij - clusters van 32 kB kost ook een file van ��n byte je 32 kB. - - De volgende partitie(s) kun je dan natuurlijk wel zo groot - mogelijk maken. De max. grootte van een partitie is 32 MB. - Als je het �cht maximaal neemt, krijg je clusters van 32 kB. - Ik heb daarom even gekeken of dit niet beter kon. En het k�n - beter. Als je als grootte 32686 kB neemt (bij FDISK van MK), - krijg je met een FAT van 12 sectoren clusters van 16 kB. - - Ik heb op mijn 80 MB HD gekozen voor de volgende indeling: - - A: 4096 kB 2 sectoren per cluster - B: 32686 kB 16 sectoren per cluster - C: 32686 kB 16 sectoren per cluster - D: 13456 kB 8 sectoren per cluster - - R O O T D I R - - Je moet voorkomen dat er veel files in de rootdirectory - komen te staan. Je kunt het beste alleen COMMAND2.COM, - MSXDOS2.SYS, AUTOEXEC.BAT en REBOOT.BAT in de root laten - staan. Dit is niet alleen voor de overzichtelijkheid, maar - komt ook de snelheid ten goede. Bij het opstarten worden de - juiste files meteen gevonden. - - De rootdirs van de andere partities kun je het beste - helemaal leeg laten. Daar mogen eigenlijk alleen maar - subdirectory's in staan. - - Bij FDISK kun je daarom ook het beste de dirgrootte op 64 - bestanden zetten. Dit is het kleinste. - - - S U B D I R S - - Zoals gezegd komen op A: programma's die vaak gebruikt - worden. Ik heb zelf de volgende (1e graads) subdirectory's - op A: - - BASIC - BASIC tools (bijv. Flexkist, KUN-BASIC) - BATCH - batchfiles - CRUNCH - allerlei crunchers en decrunchers - MEMMAN - MemMan - ML - machinetaal tools (bijv. GEN80, MSXDEBUG) - UTILS - allemaal utility's - VIEW - MSX-View - - In MEMMAN zit weer de subdirectory TSRS, dit om het een - beetje overzichtelijk te houden. Als er 30 TSR's tussen - andere files staan, wordt het een beetje onduidelijk. - - UTILS moet ik nog eens goed indelen: bepaalde (2e graads) - subdirectory's voor bijv. tekst-tools (TED, wordcount) en - turbo R tools (READKANA, ROMTURBO). - - MSX-View bevat uiteraard allerlei subdirs met files die - bestemd zijn voor View zelf. - - - A N D E R E P A R T I T I E S - - Ik heb het zelf nog niet goed ingedeeld, omdat ik nog mijn - BBS op deze HD heb staan. Maar zodra ik weer "echt" online - ben, zal ik het BBS op een aparte HD zetten (20 MB is meer - dan genoeg voor een BBS). - - Dan wil ik op B: muziek (MOD-files, MoonBlaster, - Soundtracker, SME 3) zetten, op C: tekst, informatie en - (mijn) sources en op D: spellen. - - Kasper Souren diff --git a/sunrise_special/4/HEX Printen.md b/sunrise_special/4/HEX Printen.md deleted file mode 100644 index 2b7699f..0000000 --- a/sunrise_special/4/HEX Printen.md +++ /dev/null @@ -1,75 +0,0 @@ - N O G M A A L S H E X P R I N T E N - - - Op Sunrise Special #3 stond een tekst van mij over het - printen van een binair, hexadecimaal of decimaal getal in - ML. De decimale routine was goed en de binaire zeer mooi, - maar de hexadecimale was nogal eh... vreemd geprogrammeerd. - Dat komt ervan als je na 2:00 's nachts nog teksten voor de - Special gaat schrijven! - - Om het goed te maken hierbij een fatsoenlijke routine om een - getal hexadecimaal af te drukken. Onderstaande source stuurt - de waarde in A hexadecimaal naar het scherm. - - PRTHEX: LD C,A ; bewaar A voor andere helft - AND &HF0 ; bovenste nibble - RRCA - RRCA - RRCA - RRCA ; verschuif naar onderste - CALL UITHEX ; printen - LD A,C ; oude waarde weer terug - AND &H0F ; onderste nibble - CALL UITHEX ; printen - RET - UITHEX: ADD A,"0" - CP "9"+1 ; is het een cijfer? - JP C,CIJFER ; ja, dan printen - ADD A,"A"-"9"-1 ; nee, dan letter van maken - CIJFER: CALL &HA2 ; BIOS routine CHPUT - RET - - - S P A G H E T T I - - Dit is een nette routine. Er zullen echter programmeurs zijn - die zeggen dat het sneller kan. Dat kan ook wel, en het - werkt ook wel, maar het is dan niet zo netjes meer. Je - krijgt dan het volgende: - - PRTHEX: LD C,A - AND &HF0 - RRCA - RRCA - RRCA - RRCA - CALL UITHEX - LD A,C - AND &H0F - UITHEX: ADD A,"0" - CP "9"+1 - JP C,&HA2 - ADD A,"A"-"9"-1 - JP &HA2 - - Het is korter en sneller, en toch zou ik het nooit zo - programmeren. In zo'n kleine routine kun je niet zo gauw van - spaghettistijl spreken, maar dit begint er aardig op te - lijken. De routine roept namelijk halverwege zijn staart al - een keer aan, en dat soort dingen vallen nu eenmaal onder de - noemer "spaghetti". Ook het vervangen van CALL &HA2 en RET - door een JP en is niet echt netjes, en het weglaten van de - tweede CALL UITHEX al helemaal niet. - - Maar goed, welke routine u ook kiest, het is in ieder geval - beter dan die maffe routine van de vorige keer (al was dat - geen spaghetti!). - - Stefan Boer - - - Nvdr. Hier verschillen Stefan en ik duidelijk van mening. - Vandaar dat ik deze tekst toch laat staan. In het stukje - over een goede random routine gebruik ik nl. de routine die - volgens Stefan "fout" is. diff --git a/sunrise_special/4/Index registers.md b/sunrise_special/4/Index registers.md deleted file mode 100644 index fb3f31c..0000000 --- a/sunrise_special/4/Index registers.md +++ /dev/null @@ -1,198 +0,0 @@ - I N D E X R E G I S T E R S - - - De Z80 is uitgerust met twee indexregisters, IX en IY. Deze - registers worden door beginnende ML programmeurs vaak niet - of op de verkeerde manier gebruikt. In dit artikel zal ik - uitleggen waarvoor je de indexregisters goed kunt gebruiken - en hoe, en waarvoor niet. Eerst even een korte uitleg voor - degenen die nog helemaal niets van IX en IY weten. - - - I E N X ? - - De registers IX en IY zijn beiden 16 bits, maar ze kunnen - (bij de Z80 althans) niet op dezelfde manier worden - gesplitst als de andere 16 bits registers: BC, DE en HL. Het - is dus onzin om het hoge deel van IX met I aan te duiden, - vooral omdat het I register al bestaat en een totaal andere - functie heeft. Bij de R800 kunnen IX en IY wel worden - gesplitst, maar dat wordt aangeduid met IXL en IXH, resp. - IYL en IYH. IX betekent gewoon Indexregister X. - - - G E I N D E X E E R D E A D R E S S E R I N G - - De naam zegt het al: IX en IY kunnen worden gebruikt voor - ge�ndexeerde adressering. Dit werkt ongeveer hetzelfde als - indirecte adressering, met het verschil dat er bij het door - het register gegeven adres nog een constante wordt opgeteld. - Dit klinkt misschien erg ingewikkeld, maar met een simpel - voorbeeld is het al snel duidelijk hoe het werkt. - - LD IX,TABEL - LD A,(IX+3) - - Eerst wordt in IX het beginadres van een tabel geladen, en - daarna wordt de vierde (!) byte uit die tabel in A geladen. - Bijna alle instructies met HL en (HL) zijn er ook voor IX en - IY, waarbij (HL) dan wordt vervangen door (IX+d). Dit was - overigens niet de slimste manier om dit te programmeren, het - volgende is niet alleen korter maar ook veel sneller: - - LD A,(TABEL+3) - - En zo kom ik bij het eigenlijke onderwerp van dit artikel: - wanneer heeft het zin om de indexregisters te gebruiken en - wanneer niet. - - - V A R I A B E L - - Eigenlijk is het heel simpel: het heeft alleen zin om de - indexregisters te gebruiken als de waarde van de index- - registers variabel is. - - Wat bedoel ik daarmee? Even terug naar het voorbeeld: - - LD IX,TABEL - LD A,(IX+3) - - De waarde van IX is hier niet variabel, die is namelijk - altijd gelijk aan TABEL. Daarom kan er dus beter een - absolute adressering worden gebruikt: - - LD A,(TABEL+3) - - Dit is niet alleen korter en sneller, je gebruikt bovendien - minder registers. Het heeft wel zin om de indexregisters te - gebruiken als de waarde van de indexregisters variabel is - Dit komt bijvoorbeeld voor bij tabellen die uit entry's zijn - opgebouwd die langer zijn dan 1 byte. Het is dan erg - makkelijk om IX of IY telkens naar het begin van een entry - uit de tabel te laten wijzen, want dan kunnen de gegevens - uit op zeer eenvoudige wijze uit die entry worden gehaald. - Ik zal proberen dit duidelijk te maken met een voorbeeld. - - - L E N G T E V A N E N T R Y - - De lengte van de entry is maximaal 128. d is g��n unsigned - byte, dus 255 is eigenlijk -1. Als het indexregister naar - het begin van de entry wijst, kunnen er 127 andere byte - boven het begin en 128 bytes onder het begin. - - - V E C H T R O U T I N E - - Als ik de vechtroutine voor Pumpkin Adventure III ga - schrijven, dan komen daar zeker indexregisters aan te pas. - Stel ik heb de volgende tabel met de gegevens van de - vijanden: - - ENDAT: DB 100,20,25 ; vijand #0 - DB 200,50,40 ; vijand #1 - DB 150,30,35 ; vijand #2 - - ENDAT staat voor ENemy DATa, de getallen zijn achtereen- - volgens power, strength en defense. In werkelijkheid zijn er - natuurlijk veel meer vijanden en veel meer gegevens per - vijand. - - De lengte van een entry in deze tabel is 3 bytes. Het begin - van de vechtroutine zou er dan als volgt uit kunnen zien: - - ENEMY: LD B,A - ADD A,A - ADD A,B ; A=A*3 - LD C,A - LD B,0 - LD IX,ENDAT - ADD IX,BC - - Bij aanroep van de routine staat in A het nummer van de - vijand. We vermenigvuldigen dit eerst met de lengte van een - entry (3) en tellen dat vervolgens bij het beginadres van de - tabel op. In IX staat nu het beginadres van de entry dat bij - de juiste vijand hoort. Het is nu heel eenvoudig om power, - strength en defense uit te lezen, want op (IX+0) staat de - power, op (IX+1) de strength en op (IX+2) de defense. Het is - hopelijk duidelijk dat IX hier een variabele waarde heeft, - die is immers afhankelijk van de gekozen vijand. - - Dit is ook wel met HL te programmeren, en dat is soms zelfs - iets sneller, maar dat is een stuk minder makkelijk omdat je - dan met INC en DEC instructies moet zorgen dat HL naar de - gewenste positie in de entry wijst. Als je bijvoorbeeld - eerst het gegeven op (IX+3) nodig hebt en daarna dat op - (IX+28), dan is dat met indexregisters een fluitje van een - cent, terwijl je met HL iets als - - LD BC,25 - ADD HL,BC - - zult moeten gaan gebruiken, waarbij je dus ook nog het BC - (of DE) register nodig hebt. Bovendien is het prettig om HL - vrij te hebben voor andere zaken. - - De indexregisters kunnen dus zeer goed worden toegepast bij - het werken met tabellen waarvan de entry's uit meerdere - bytes bestaan. - - - L D I X , B C ? - - Een LD IX,BC instructie bestaat niet, en ook LD BC,IX, LD - DE,IY etc. zijn niet aanwezig. Gelukkig is daar een simpel - truukje voor: PUSHen en POPpen. Bijvoorbeeld: - - PUSH BC - POP IX ; LD IX,BC - - PUSH IY - POP DE ; LD DE,IY - - - S T R I N G S M E T U S R - - Ik zie vaak dat er een indexregister wordt gebruikt bij het - verwerken van een - - A$=USR(B$) - - aanroep vanuit BASIC. De BASIC interpreter zet in DE het - beginadres van drie bytes waar de string wordt beschreven - door de lengte op (DE) en het beginadres op (DE+1), en - springt vervolgens naar de ML routine. Je wilt nu de lengte - in B hebben en het beginadres van de string in DE. Dit wordt - vaak zo geprogrammeerd: - - PUSH DE 1 11 - POP IX 2 14 - LD B,(IX+0) 3 19 - LD E,(IX+1) 3 19 - LD D,(IX+2) 3 19 - --- ---- - 12 82 - - Dit zijn 12 bytes en 82 T-states. Het kan echter korter: - - EX DE,HL 1 4 - LD B,(HL) 1 7 - INC HL 1 6 - LD E,(HL) 1 7 - INC HL 1 6 - LD D,(HL) 1 7 - --- --- - 6 37 - - Dit is ��n regel meer in assembly, maar het zijn slechts 6 - bytes en 37 T-states. Dus twee keer zo kort en meer dan twee - keer zo snel. Hoewel de waarde van IX hier wel variabel is, - is het hier dus toch beter om HL te gebruiken. HL had hier - toch geen waarde die je nog nodig hebt, en bovendien hoeven - de gegevens hier maar ��n keer en op volgorde te worden - gelezen. Het werken met indexregisters heeft vooral - voordelen als je de gegevens door elkaar nodig hebt. - - Stefan Boer diff --git a/sunrise_special/4/Kun-Basic Cursus.md b/sunrise_special/4/Kun-Basic Cursus.md deleted file mode 100644 index 47d06ca..0000000 --- a/sunrise_special/4/Kun-Basic Cursus.md +++ /dev/null @@ -1,435 +0,0 @@ - K U N - B A S I C C U R S U S - - - Vorige keer had ik tegen Kasper Souren (hoofdredacteur van - jullie meest geliefde diskmagazine) gezegd dat ik deze keer - misschien een programma om vector-graphics te maken in BASIC - zou plaatsen. Helaas zag dhr. Souren dit als een belofte. - Dit programma heb ik wel al, het werkt ook, maar nog niet - helemaal zoals ik het wil. Ook heb ik te maken gehad met een - "disk-crash" waar dat programma op stond en ik had geen - kopie... Ik heb nu een cursus geschreven (in ��n deel) voor - het gebruik van de KUN-BASIC compiler, het programma dat ik - heb gebruikt voor het vector-graphics programma, voor - ALPHA.BAS (zie SRS #3) en ook voor de fractal-makers die op - deze disk staan. Voor deze cursus heb ik o.a. gebruik - gemaakt van de gegevens uit de MSX2+ handleiding van MK. - - De KUN-BASIC compiler (ik kort het vanaf nu af tot BC: Basic - Compiler) is een in gebruik snelle en handige compiler voor - het compileren (=naar machinetaal omzetten) van MSX-BASIC. - Door gebruik te maken van de BC worden uw BASIC programma's - vele malen sneller. In het geval van ALPHA.BAS heb ik - gemerkt dat de ronddraaiende balletjes op 7 MHz even snel - draaien als op 3.5 MHz. De snelheid werd dus enkel bepaald - door de VDP en niet meer door BASIC - - Er zijn verschillende versies in omloop: eentje voor MSX2 - computers en eentje die ook de MSX2+ commando's kan - compileren (waarempel uit mijn computer "gesloopt") (Nvdr: - geen commentaar.). Beide versies kunnen op disk of in ROM - staat. Disk-versies moeten met BLOAD"naam",R worden - opgestart, ROM versies worden met CALL BC [enter] vanuit - BASIC geactiveerd. - - Deze compiler heeft als voordeel dat je gewoon in MSX-BASIC - blijft en dat je zelf kunt kiezen welke delen van het - programma gecompileerd worden, zodat je toch ook - niet-compileerbare commando's in het zelfde programma kunt - gebruiken. (later meer hierover.) Bovendien hoef je niet - allerlei apparte programma's op te starten om het te - compileren. - - - D R I E I N S T R U C T I E S - - Om een programma te compileren zijn er 3 instructies - toegevoegd: - - CALL RUN - CALL TURBO ON - CALL TURBO OFF - - Noot: CALL kan ook als underscore, "_" ingetikt worden. - - CALL RUN compileert het hele BASIC programma dat in het - geheugen staat, bijvoorbeeld: - - 10 SCREEN 8 - 20 FOR I=0 TO 255 - 30 LINE(I,0)-(I,211),I - 40 NEXT I - - Nadat u dit heeft ingevoerd, kunt het programma eerst eens - gewoon RUNnen, en daarna CALL RUN [enter] intikken. De - uitvoer is precies het zelfde; van het compileren merkt u - niets, dat gaat behoorlijk snel. Na CALL RUN is de uitvoer - wel een stuk sneller. CALL RUN"filenaam" werkt (helaas) - niet. - - - N I E T - W E R K E N D E C O M M A N D O 'S - - Er zijn commando's die de compiler niet kan compileren. Dit - zijn vooral de commando's voor disk-drive, printer en - geluids-chips. Hieronder is een reeks van niet-compileerbare - commando's weergegeven. - - AUTO, BASE BLOAD, BSAVE, CALL, CDBL, CINT, CLEAR, CLOAD, - CLOSE, CONT, CSAVE, CSNG, CVD, CVI, CVS, DEFFN, DELETE, - DRAW, DSKF, EOF, ERASE, ERL, ERR, ERROR, EQV, FIELD, FILES, - FPOS, FRE, GET, IMP, INPUT#, KEYLIST, LFILES, LINE INPUT#, - LIST, LLIST, LOAD, LOC, LOF, LPRINT USING, LSET, MAXFILES, - MERGE, MOTOR, MKD$, MKI$, MKS$, NAME, NEW, ON ERROR GOTO, - OPEN, PLAY, PRINT#, PRINT #USING, PRINT USING, PUT KANJI, - RENUM, RESUME, RSET, SAVE, SPC, TAB, TRON, TROFF, WIDTH - - Het lijkt heel wat, maar het is in de praktijk best op te - vangen. Nadeel vind ik dat PLAY en DRAW niet gecompileerd - kan worden. (SOUND echter weer wel.) Als u de versie voor 2+ - op een MSX2 gebruikt worden de commando's SET SCROLL e.d. - toch gecompileerd, maar heeft geen uitwerking. Je kunt - echter wel gewoon horizontaal scrollen met SET SCROLL. Maar - VDP(24) werkt dan even makkelijk. - - - Om toch b.v. een andere breedte (WIDTH) te kiezen is het - volgende mogelijk: - - 10 WIDTH 40 - 20 CALL TURBO ON - 30 PRINT "...." - ... - ... - 100 CALL TURBO OFF - - Nu wordt alleen het stuk tussen CALL TURBO ON en CALL TURBO - OFF gecompileerd. Een ander voorbeeld: - - 10 SCREEN 8:SET PAGE 0,1 - - Regel 10 zou ook gecompileerd kunnen worden, maar is te - omslachtig.) - - 20 BLOAD"PICTURE.PIC",s - - BLOAD kan niet gecompileerd worden. - - 30 CALL TURBO ON - 40 SET PAGE 0,0 - 50 FOR I=0 TO 211 - 60 COPY(0,I)-(255,I),1 TO (0,0),0 - 70 NEXT I - - De regels hierboven worden snel uitgevoerd. - - 80 CALL TURBO OFF - 90 OPEN"GRP:" FOR OUTPUT AS#1 - 100 PRESET(10,200):COLOR 255 - 110 PRINT #1,"Mooi he?" - 120 GOTO 120 - - OPEN en PRINT# kunnen niet gecompileerd worden. - - - B E P E R K T E C O M M A N D O 'S - - Van sommige commando's kunnen niet alle opties of parameters - gecompileerd worden: - - CIRCLE Start- en eindhoeken en mate van afplatting kunen - niet gecompileerd worden. - COPY Alleen graphische copy. - DEFDBL Zelfde werking als DEFSNG. - DIM Moet als eerste na CALL TURBO ON staan of vooraan - in een programma. - END Springt naar de regel NA CALL TURBO OFF, stopt het - programma dus niet! - INPUT Maximaal INPUT van ��n variabele, dus niet "INPUT - A,B". - KEY Alleen ON KEY GOSUB en KEY(x) ON/OFF toegestaan. - LOCATE X en Y coordinaat moeten allebei gegeven worden. De - switch cursor aan/uit (LOCATE X,Y,s(0/1)) is niet - toegestaan. - NEXT Variabele moet er ALTIJD achter staan, dus NIET - alleen NEXT, maar b.v. NEXT I of NEXT X,Y. - ON Men zegt dat ON STOP GOSUB en ON INTERVAL=X GOSUB - niet werken, wegens een bug, maar ik heb niets - gemerkt. (Ik heb echter alleen de versie voor - MSX2+!) - PRINT De komma-functie werkt anders dan normaal. - PUT Alleen PUT SPRITE toegestaan. - SCREEN Alleen scherm-modus en sprite-grootte kunnen - opgegeven worden. - SET Alleen SET PAGE en SET SCROLL (2+ versie) - toegestaan. - STOP Zelfde werking als END - USR De parameter kan alleen maar een integer zijn. - VARPTR File-nummer kan niet gegeven worden als parameter. - - - Er zijn ook een paar nieuwe opties toegevoegd: - - '#I Staat voor INLINE. Hiermee kunt u stukjes - machinetaal eenvoudig tussenvoegen. Bijv.: - - 10 CALL TURBO ON - 20 DEFINT I - 30 I=1 - 40 '#I &H2A,I% - 50 '#I &HF3,&HCD,@70,&HFB - 60 END - 70 'SUBROUTINE - 80 .. - 90 RETURN - 100 CALL TURBO OFF - - Regel 40 betekent: LD HL,(i) ; I moet integer zijn.) - Regel 50 betekent: DI - CALL @70 ; CALL naar regel 70. Let op! - ; Wordt niet mee geRENUMd! - EI - - - '#C +/- Zet het zogenaamde CLIPPEN aan of uit. Clippen - houdt in dat als de waarde van een y-coordinaat - groter is dan het beeld aankan, b.v. groter dan - 211, er net gedaan wordt alsof de y-waarde gelijk - is aan de maximale y-waarde, in het voorbeeld dus - 211. Geldt niet voor PAINT en CIRCLE - - Voorbeeld: - - 10 CALL TURBO ON - 20 SCREEN 5 - 30 '#C- - 40 LINE(0,0)-(255,255) (y geCLIPt) - 50 IF INKEY$="" THEN 50 - 60 '#C+ - 70 LINE(0,0)-(255,255) (y niet geCLIPt) - 80 IF INKEY$="" THEN 80 - 90 CALL TURBO OFF (Kan weggelaten worden) - - - #N +/- Kijkt of de waarde van de variabele tijdens een - NEXT overloopt. Als #N+ gegeven is, wordt de fout - net zoals in normaal BASIC afgehandeld. - - Voorbeeld: - - 10 CALL TURBO ON - 20 FOR I%=0 TO 100000 - 30 NEXT I% - 40 CALL TURBO OFF - - Als u dit programma RUNt blijft het oneindig doorlopen, - omdat I% (een integer) nooit 100000 kan bereiken. Als u 15 - '#N+ invoegt eindigt het net zoals normaal in een "Overflow - in 30" Deze switch vertraagt de uitvoering van het - programma, gebruik het dus alleen als het nodig is. '#N- zet - deze controle-fuctie weer uit. - - - T I P S E N O P M E R K I N G E N - - In normaal BASIC kunnen "oneindige" programma's met - [CTRL][STOP] toch gestopt worden. Dit kan tijdens de uitvoer - van een gecompileerd programma niet! Voorbeeld: - - 10 PRINT"Hallo! "; - 20 GOTO 10 - - Als u dit gewoon RUNt kunt u het altijd afbreken met - [CTRL][STOP], maar als u dit CALL RUNt kan dat niet. De - enige mogelijkheid om toch te stoppen is de computer te - resetten of uit te zetten! En daarmee het verlies van uw - programma. Hier wat oplossingen van dit probleem: - - 10 PRINT"Hallo! "; - 20 IF INKEY$="" THEN GOTO 10 - - Nu zal het programma altijd afbreken zodra er een toets - wordt ingedrukt. Natuurlijk werkt "ON STOP GOSUB" ook, maar - dit vertraagt de snelheid van het programma. - - - Andere oplossing: - - Tik voor dat u begint de POKE&HFBB0,1 in. Nu kunt u altijd - met [CTRL][SHIFT] [GRAPH][CODE] het programma verlaten en - valt u terug in BASIC. Let op als u het programma onderbrak - terwijl u NIET in een tekstscherm was! Dan ziet u niets - meer. Tik dan SCREEN 0. - - - Nog een oplossing: - - Dit is meer een nood-oplossing, voor als er toch nog iets - mis is gegaan en u de computer hebt moeten resetten: dus na - een reset, tik dan in: POKE32770,128: POKE32769,1:LIST - [ENTER] Nu ziet u dat telekens de eerst regel van het - programma weergegeven wordt. Druk op [CTRL][STOP] om het - listen te onderbreken en tik dan ALLEEN het regelnummer van - de eerste regel in en druk op ENTER. Nu kunt u uw programma - normaal listen en op diskette wegschrijven. Als u dit gedaan - heeft, kunt u het beste weer resetten en het programma - gewoon met "LOAD" in te laden, voordat u verder gaat. - Voorbeeld: - - [reset] - POKE32770,128:POKE32769,1:LIST - 10 PRINT"Hallo! "; - 10 PRINT"Hallo! "; - 10 PRINT"Hallo! "; - 10 PRINT"Hallo! "; [CTRL][STOP] - Ok - 10 [ENTER] - list - 10 PRINT"Hallo! "; - 20 GOTO 10 - Ok - save "naam.bas",a - - - V R E E M D E D I N G E N - - De BC vindt een string-formule al snel te complex en zal dan - ook snel met de "String formula too complex"-error aankomen. - - Als er bij een goto naar een regel gesprongen wordt die niet - bestaat, zal de BC altijd de als fout-regel de regel met - CALL TURBO OFF geven. B.v. - - 10 CALL TURBO ON - 20 GOTO 25 - 30 PRINT "TJA..." - 40 CALL TURBO OFF - - RUN - Undefined line number in 40 - - Daar staat echter niets verkeerds. Zeker bij groter - programma's is de fout vaak moeilijk op te sporen. Hier een - truuk om de fout snel te vinden. - - RENUM 55555,55555,55555 - - Zorg ervoor dat er geen regelnummers na 55555 voorkomen, - anders gebeurt er wel wat. Er zal niets met uw listing - gebeuren, maar er wordt wel gemeld dat er naar een - niet-bestaande regel gesprongen wordt in regel 20. - - De disk-versies van de BC nemen de memory-map page 2 en 3 in - beslag, dus let op met een RAM-disk. Bij mijn ROM-versie heb - ik die problemen niet gehad. - - Nvdr: de ROM versie zet zichzelf ook in pagina 2 van de - memory mapper. Daarom is CALL BC nodig om te initialiseren. - KUN zit bij MSX2+'en op page 2 van het ROM. Dus van #8000 - tot en met #bfff. Bij de turbo R kun je met het programma - READKANA (zie deze disk) een programma in de DRAM laden, dan - kost het alleen je Kanji ROM, als je de DRAM mode aan hebt. - - Het gecompileerde programma wordt ook in page 2 en 3 gezet, - net als het bron-BASIC programma, maak het bron-programma - dus niet te groot. - - Alle variabelen BUITEN het TURBO blok zijn niet toegankelijk - IN het TURBO blok en vice versa. Doc integers (zowel enkele - variabelen als arrays) kunnen wel meegenomen worden naar het - TURBO blok en weer naar buiten. Voorbeeld: - - 10 DIM A%(5) - 20 B%=4:C%=3 - 30 FOR I=1 TO 5:A%(I)=4-I:NEXT I - 40 CALL TURBO ON ( A%() , B% ) - 50 B%=B%+1 - 60 FOR I=1 TO 5:A%(I)=I+3:NEXT I - 70 PRINT B%,C% - 80 FOR I=1 TO 5:PRINT A%(I); - 90 CALL TURBO OFF - 100 PRINT B%,C% - 110 FOR I=1 TO 5:PRINT A%(I); - - RUN - 5 0 - 4 5 6 7 8 - - 5 3 - 4 5 6 7 8 - - - Dubbele precisie-variabelen IN het TURBO blok hebben een - nauwkeurigheid van 4,5 decimalen. Voorbeeld: - - 10 CALL TURBO ON - 20 PI=3.1415926535897 - 30 PRINT PI - 40 CALL TURBO OFF - - RUN - 3.1416 - - - CALL TURBO ON en CALL TURBO OFF mogen niet genest worden. - Voorbeeld: - - 10 CALL TURBO ON - 20 I=1 - 30 IF I=1 THEN CALL TURBO OFF:GOTO 300 - 40 .. - 50 CALL TURBO OFF - .. - .. - 300 .. - - Als dit programma geRUNd wordt zal er een foutmelding - verschijnen. - - - V E R S N E L L E N - - Om de snelheid van uitvoer op te voeren kunt u het volgende - doen: - - Gebruik zoveel mogelijk integer variabelen. - - Voor grafisch werk zonder sprites: voeg dit in: - VDP(9)=VDP(9) OR 2. Dit schakelt het sprite-systeem uit, - zodat de VDP meer tijd over heeft om de andere zaken uit te - voeren. Dit kan juist het laatst beetje extra snelheid zijn - dat uw programma nodig heeft om "smooth" te zijn. Om het - sprite-systeem weer aan te schakelen: VDP(9)=VDP(9) AND 253. - - - N A D E L E N - - Een nadeel is dat het gecompileerde programma niet apart op - disk gezet kan worden, zoals MCBC wel kan. Een ander nadeel - is de vrij grote onnauwkeurigheid van de reals (dubbele - precisie variabelen). Voor het tekenen van fractals e.d. kan - met niet al te nauwkeurig de coordinaten ingeven. (Zie ook - deze disk). - - De lijst van niet te compileren opdrachten zie ik niet als - nadeel. Het zijn meestal de I/O opdrachten en de snelheid - van uitvoeren ligt dan vaak aan het apparaat zelf. - - De BC is (volgens mij) vooral geschikt voor grafisch werk in - BASIC. Je kunt er zelfs op een normale MSX2 een horizontale - smooth-scroll over het hele scherm in SCREEN 5 mee maken. - (zie vorige SRS, ALPHA.BAS) - - Ook de maximale grootte van het bron-programma is toch wel - beperkt. Op MSX2 en hoger valt dat enigzins op te vangen - door slim gebruik te maken van de memory-mapper, maar dan - zit je met de variabelen te kijken, die moeten dan in page 4 - of in het VRAM, wat de snelheid niet bevordert. - - Na, dat was het wel. Zijn er vragen over (KUN-)BASIC, - schrijf dan gerust naar de Sunrise postbus t.a.v. - ondergetekende. - - Tot de volgende keer, met (misschien) een - vector-graphics-maker in KUN. Programmeer ze! En je weet - het: programmeren in BASIC: moet KUNnen! - - Randy Simons diff --git a/sunrise_special/4/MSX Audio.md b/sunrise_special/4/MSX Audio.md deleted file mode 100644 index 1c93d54..0000000 --- a/sunrise_special/4/MSX Audio.md +++ /dev/null @@ -1,95 +0,0 @@ - M S X A U D I O - - - Ik heb dit programma geschreven om de Music Module te - gebruiken bij Compile spellen die op HD staan (en niet naar - BASIC te hoeven). De syntax is: - - MSXAUDIO [ON|OFF] - - Bij ON wordt de MSX-AUDIO chip goed gezet zodat Compile - spellen hem herkennen. Het kan zijn dat bepaalde programma's - hierdoor blijven hangen. De EXTBIO hook wordt nl. gewoon - aangepast ("POKE -54,35"). Indien iemand weet hoe het wel - volgens de standaard kan, of in het bezit is van een �chte - MSX-AUDIO cartridge: laat het even weten. Ik ben dus - ge�nteresseerd in de waarden die op adres #ffca t/m #ffce - staan. - - - D E S O U R C E - - BDOS: EQU 5 - FCB1: EQU #5c - - in a,(#c0) - inc a ;c hoog -> a was 255 - ; -> geen AUDIO - jr c,NoAUDIO - - Als op poort #c0 de waarde 255 staat, is er geen MSX-AUDIO - aanwezig. - - ld hl,#ffca - ld a,(FCB1+2) - cp "F" - jr z,Off - cp "f" - jr nz,On - - FCB1 bevat de tekst die achter de COM file wordt meegegeven, - maar dan wel in zo'n vorm dat je er meteen een FCB mee kunt - openen. Ik check alleen of er een "F" staat op het tweede - karakter van de filenaam. Alles behalve dit betekent dat - MSX-AUDIO aan wordt gezet. - - - Off: ld a,i - ld (hl),a - ld de,tOff - jr Print - - Om hem ook uit te kunnen zetten heb ik iets gedaan wat - eigenlijk niet mag. Ik heb register I ervoor gebruikt. Voor - zover ik weet wordt het niet door andere programma's - veranderd, en is (was...) het dus een uitstekende plaats om - iets in te zetten dat even bewaard moet blijven. - - - On: ld a,(hl) - ld i,a - ld a,35 ;? - ld (hl),a - ld de,tOn - jr Print - - Ik weet niet precies waarom er 35 op #ffca moet komen, want - de mnemonics die dan aan die hook hangen slaan nergens op. - Vandaar ook dat de computer blijft hangen als er andere - programma's gerund worden die die hook gebruiken. Bijv. TED. - Dat is tevens de reden dat ik een off-optie heb gemaakt. - - - NoAUDIO: ld de,tNoAUDIO - Print: ld c,9 - jp BDOS - - tOn: db "Your non-standard MSX-AUDIO chip " - db "can now be used as a " - db "standard Panasonic",13,10 - db "MSX-AUDIO module.",13,10,"$" - - tOff: db "EXTBIO hook is restored.",13,10,"$" - - tNoAUDIO: db "No MSX-AUDIO chip available.",13,10 - db "$" - - - N O O T - - Ik weet ook wel dat het niet klopt allemaal, en dat het - eigenlijk niet mag volgens de standaard. Maar het programma - is handig wanneer je je Music Module wilt gebruiken bij - spellen van Compile op HD. - - Kasper Souren diff --git a/sunrise_special/4/NTM Coordin.md b/sunrise_special/4/NTM Coordin.md deleted file mode 100644 index 08638c2..0000000 --- a/sunrise_special/4/NTM Coordin.md +++ /dev/null @@ -1,204 +0,0 @@ - N T M C O O R D I N - - - G E B R U I K - - Deze TSR was een ideetje van CTS, en ik heb hem gemaakt. Je - kunt zo heel simpel in BASIC bepalen op welke coordinaat de - cursor staat. Deze coordinaten worden nl. op F1 en F2 gezet. - - Als je ESC inhoudt, blijven de waarden onder F1 en F2 - ongewijzigd. Je kunt zo makkelijk de coordinaten in een - BASIC-programma gebruiken. - - Onder TED levert deze TSR problemen op, omdat nu gewoon de - x- of y-coordinaat op het scherm komt als je op F1 of F2 - duwt. - - Bij het verwijderen worden de oude functietoets-instellingen - weer hersteld. - - - B E S P R E K I N G S O U R C E - - Ik zal alleen de gedeelten bespreken die specifiek voor - Coordin zijn. - - Hook EQU #FDA9 ;H.DSPC: aan begin van - ;routine die cursor - ;zichtbaar maakt - - Bij het zoeken naar een geschikte hoek vond ik H.DSPC. Als - je de routine aan de interrupt hangt, wordt de routine veel - te vaak uitgevoerd. Dat heeft dus geen nut(h). Bij deze hook - wordt de routine alleen uitgevoerd als hij nodig is. - Namelijk vlak voordat de cursor op het scherm wordt gezet. - - - X_coor: EQU #F3DD - Y_coor: EQU #F3DC - FNKST: EQU #F87F - DSPFNK: EQU #00CF - - Dit zijn de benodigde adressen. X_coor en Y_coor zijn gewoon - de coordinaten van de cursor. FNKST is het adres waar de - data van de functietoetsen staat. Met DSPFNK kun je de - functietoetsen aan zetten. - - - Kill: LD HL,Buffer - LD DE,FNKST - LD BC,32 - LDIR - - LD A,(#F3DE) ;F-keys aan? - OR A - JP NZ,DispKeys - RET - - Kopieer eerst de data naar een buffer om de functietoetsen - te herstellen na verwijderen van de TSR. Als de - functietoetsen aan staan, wordt de herstelde tekst ook weer - op het scherm gezet. Dit met de routine DispKeys. - - - Program: PUSH AF - PUSH BC - PUSH DE - PUSH HL - - Ik weet niet welke registers wel of niet veranderd mogen - worden, maar dit is het veiligst. - - - DI - IN A,(#AA) - AND 240 - OR 7 - OUT (#AA),A - IN A,(#A9) - EI - AND %100 - JR Z,Quit - - Leest rij 7 van het toetsenbord. AND 240 is om de high - nibble niet aan te passen. OR 7 zorgt dat rij 7 wordt gezet. - ESC is de derde toets in de rij, dus AND %100. Als ESC is - ingedrukt wordt de routine be�indigd. De functietoetsen - mogen dan niet worden aangepast. - - - LD A,(X_coor) - LD HL,FNKST - CALL HexDec - - A is waarde van toets en HexDec zet die als ASCII op adres - FNKST. - - LD A,(Y_coor) - LD HL,FNKST+16 - CALL HexDec - - Idem. - - LD A,(#F3DE) ;F-keys aan? - OR A - CALL NZ,DSPFNK - - Als functietoetsen aan staan, wordt de tekst ook op het - scherm gezet. - - - Quit: POP HL - POP DE - POP BC - POP AF - RET - - Registers weer herstellen en terugspringen naar de TSR - handler. - - - HexDec: DEC A ;E�n verminderen, - ;coordinaten van LOCATE - ;werken anders dan de - ;coordinaten op #F3DC en - ;#F3DD - LD E,0 ;Zet E op nul - - HD2: SUB 10 ;10-tal in E - INC E - JR NC,HD2 - - Trek telkens 10 af van A, en tel telkens 1 op bij E, totdat - A kleiner dan 0 is. - - ADD A,10 - DEC E - - Dan wordt E 1 verminderd en 10 opgeteld bij A. Dit stukje - (vanaf HD2) is eigenlijk E=A MOD 10, A=A DIV 10 (of in - BASIC: A=A \ 10). - - LD B,A ;1-heid in B - - P10: LD A,E - OR A - JR Z,P1 - ADD A,"0" - LD (HL),A - INC HL - - Maak even een ASCII waarde van E en B. Als E nul is, wordt B - opgeschoven. Daarom wordt INC HL alleen gedaan als E niet 0 - is. (Oftewel, bij de waarde 10 in A krijg je "10" en bij 9 - krijg je niet niet "09" maar "9".) - - P1: LD A,B - ADD A,"0" - LD (HL),A - INC HL - LD (HL),0 - RET - - Zet de waarden nog even op de juiste plaats. - - - Buffer: DS 32 ;Voor de oude waarden van de - ;functietoetsen - - - Nog even een stukje van de Init routine: - - LD HL,FNKST - LD DE,Buffer - LD B,32 - Loop: LD A,(HL) - LD (DE),A - LD (HL),0 - INC HL - INC DE - DJNZ Loop - - Dit kopieert 32 bytes van de functietoetsenbuffer naar een - eigen buffertje; om de functietoetsen te herstellen bij het - verwijderen. Ik gebruik hier niet LDIR omdat ik ook de - functietoetsen wil wissen: LD (HL),0. - - LD A,(#F3DE) ;F-keys aan? - OR A - JR NZ,DispKeys - - XOR A - RET - - DispKeys: LD IY,(#FCC0) - LD IX,DSPFNK - CALL #001C - - Het is wel waarschijnlijk dat de BIOS aan staat, maar ik ga - er niet vanuit. Dit is een stuk zekerder dan gewoon CALL - DSPFNK. - - Kasper Souren - \ No newline at end of file diff --git a/sunrise_special/4/PCM Rechtstreeks.md b/sunrise_special/4/PCM Rechtstreeks.md deleted file mode 100644 index 4da5d47..0000000 --- a/sunrise_special/4/PCM Rechtstreeks.md +++ /dev/null @@ -1,346 +0,0 @@ - P C M R E C H T S T R E E K S - - - We hebben op vorige Specials al aandacht besteed aan het - aansturen van de PCM chip in de turbo R door middel van de - BIOS calls PCMPLY en PCMREC. De PCM chip kan echter ook - rechtstreeks met OUT poorten worden aangestuurd. In dit - artikel ga ik het hier over hebben, en zal ik tevens de - sources geven van de standaard opneem- en afspeelroutines. - De maximale opneemfrequentie is zo'n 25 kHz! Het afspelen - kan zelfs nog sneller, maar dat heeft dus alleen zin voor - samples die op een andere computer zijn opgenomen. - - - I / O P O O R T E N - - Voor de PCM chip zijn twee I/O poorten gereserveerd: &HA4 en - &HA5. De indeling van deze poorten is als volgt: - - MSB 7 6 5 4 3 2 1 0 LSB - - &HA5 write 0 0 0 SMPL SEL FILT MUTE ADDA - &HA5 read COMP 0 0 SMPL SEL FILT MUTE BUFF - &HA4 write DA7 DA6 DA5 DA4 DA3 DA2 DA1 DA0 - &HA4 read 0 0 0 0 0 0 CT1 C10 - - De beschikbare uitleg van deze bits is slechts zeer beknopt, - waardoor ik zelf ook niet van alle bits de exacte werking - weet. Ik geef hieronder de letterlijke tekst die ik heb. Als - je gewoon de standaardroutines gebruikt heb je het niet - nodig, maar ik geef de tekst toch maar voor het geval er - mensen zijn die er wel iets aan hebben. - - - ADDA (BUFF): Buffermode - Bepaalt de uitvoer van de D/A converter. Zet hem in geval - van D/A conversie (dubbele buffer) op 0, en in geval van A/D - conversie op 1. Verder, komt hij bij een reset op dubbele - buffer te staan (default). - - MUTE: Muting-besturing - Zet de geluidsuitvoer aan of uit. - 0: geen uitvoer (default) - 1: wel uitvoer - - N.B. Bij afspelen moet dit uiteraard altijd op 1 worden - gezet, anders hoor je niets. Als je het op 1 zet bij - opnemen, hoor je het geluid dat wordt opgenomen tegelijker- - tijd uit de luidspreker komen. - - FILT: Keuze van het invoersignaal van het - samplehold-circuit - Bepaalt, in het geval van A/D conversie, of het signaal dat - men in het samplehold-circuit invoert een signaal moet zijn - dat door een filter afgegeven wordt of een standaard signaal - moet zijn. Door 0 te kiezen wordt het een geluid van een - standaard signaal, en door 1 te kiezen wordt het een geluid - van een filter-uitgangssignaal. De default waarde is 0. - - SEL: keuze van het filter-inganssignaal - Bepaalt of het signaal dat men in het low-pass filter - invoert een signaal moet zijn dat door de D/A converter - afgegeven wordt, of dat het een signaal moet zijn dat door - de microfoonversterker wordt afgegeven. Met keuze 0: geluid - afgegeven door de D/A converter, en door 1 te kiezen, kiest - men voor geluid dat door de microfoonversterker wordt - afgegeven. - - SMPL: Samplehold-signaal - Bepaalt of het ingangssignaal gesampled of geHOLD dient te - worden. - 0: Samplen (default) - 1: HOLDen - - COMP: Uitgangssignaal van de comparator - Vergelijkt het uitgangssignaal van de samplehold en dat van - de D/A converter. - 0: D/A uitvoer groter dan samplehold uitvoer - 1: D/A uitvoer kleiner dan samplehold uitvoer - - DA7 tot DA0: D/A uitvoer data - Wanneer men PCM data afspeelt, kan met het PCm geluid - afspelen door de gebruikte data hier naartoe uit te voeren. - Het formaat van de data is absoluut binair, en 127 komt - overeen met level 0. - - CT1 en CT0: counter data - Bij elke 63.5 microseconde wordt deze waarde verhoogd. De - data die op adres &HA4 werd geschreven tegelijk met het - ophogen op het moment van een D/A conversie wordt gekopieerd - en uitgevoerd. Wanneer men op adres &HA4 schrijft, wordt de - counter gewist. - - N.B. Deze counter wordt door de BIOS routines gebruikt voor - de vier opneem- en afspeelsnelheden die daar beschikbaar - zijn. - - - A F S P E L E N - - Wie het bovenste goed heeft gelezen, heeft waarschijnlijk al - gezien dat het afspelen heel makkelijk is. Gewoon de data - naar &HA4 sturen. Met de counter van de sampler zijn maar - vier snelheden mogelijk (15.75, 7.875, 5.25 en 3.94 kHz), - maar door de systeemcounter van de turbo R (zie SRS#3) te - gebruiken, kunnen we de snelheid veel nauwkeuriger opgeven. - De PCM playroutine ziet er als volgt uit: - - ; P C M . A S C - ; Play/record routines voor turbo R PCM - ; Standaardroutines van ASCII - - ; Sunrise Special #4 - ; (c) Stichting Sunrise 1993 - - PMDAC: EQU &HA4 ; write - PMCNT: EQU &HA4 ; read - PMCNTL: EQU &HA5 ; write - PMSTAT: EQU &HA5 ; read - SYSTML: EQU &HE6 ; 3.911 us system counter - - ; Play - ; R800 only! - ; In: HL beginadres - ; BC lengte - ; E snelheid - - PLAY: LD A,&B00000011 - OUT (PMCNTL),A ; D/A mode - DI - XOR A - OUT (SYSTML),A ; reset counter - - PLAY1: IN A,(SYSTML) - CP E - JR C,PLAY1 - XOR A - OUT (SYSTML),A - - LD A,(HL) ; PCM data - OUT (PMDAC),A - INC HL - DEC BC - LD A,C - OR B - JR NZ,PLAY1 - EI - RET - - Eerst worden MUTE en ADDA op 1 gezet en SMPL, SEL en FILT op - 0. Daarna wordt de PCM data naar &HA4 gestuurd, waarbij de - systeemcounter op &HE6 wordt gebruikt voor de timing. Zoals - u ziet, zeer eenvoudig. Het opnemen gaat helaas een stuk - moeizamer, omdat we dat per bit moeten doen! - - - O P N E M E N - - Hier volgt eerst maar de source: - - ; Record - ; R800 only! - ; In: HL adres - ; BC lengte - ; E snelheid - - REC: LD A,&B00001100 - OUT (PMCNTL),A ; A/D mode - DI - XOR A - OUT (SYSTML),A ; reset counter - - REC1: IN A,(SYSTML) - CP E - JR C,REC1 - XOR A - OUT (SYSTML),A - - PUSH BC - LD A,&B00011100 - OUT (PMCNTL),A ; data hold - LD C,PMSTAT - - LD A,&B10000000 ; bit 7 - OUT (PMDAC),A ; bit convert - DB &HED,&H70 ; IN F,(C) - JP M,RECAD0 - RES 7,A - - RECAD0: SET 6,A ; bit 6 - OUT (PMDAC),A - DB &HED,&H70 - JP M,RECAD1 - RES 6,A - - RECAD1: SET 5,A ; bit 5 - OUT (PMDAC),A - DB &HED,&H70 - JP M,RECAD2 - RES 5,A - - RECAD2: SET 4,A ; bit 4 - OUT (PMDAC),A - DB &HED,&H70 - JP M,RECAD3 - RES 4,A - - RECAD3: SET 3,A ; bit 3 - OUT (PMDAC),A - DB &HED,&H70 - JP M,RECAD4 - RES 3,A - - RECAD4: SET 2,A ; bit 2 - OUT (PMDAC),A - DB &HED,&H70 - JP M,RECAD5 - RES 2,A - - RECAD5: SET 1,A ; bit 1 - OUT (PMDAC),A - DB &HED,&H70 - JP M,RECAD6 - RES 1,A - - RECAD6: SET 0,A ; bit 0 - OUT (PMDAC),A - DB &HED,&H70 - JP M,RECAD7 - RES 0,A - - RECAD7: LD (HL),A ; PCM data - LD A,&B00001100 - OUT (PMCNTL),A - POP BC - INC HL - DEC BC - LD A,C - OR B - JR NZ,REC1 - - LD A,&B00000011 - OUT (PMCNTL),A ; D/A mode - EI - RET - - Eerst worden SEL en FILT op 1 gezet en MUTE, HOLD en ADDA op - 0. De systeemcounter op &HE6 wordt net als bij de play - routine gebruikt voor de timing. Nu wordt ook de HOLD op 1 - gezet en wordt de waarde &H80 naar &HA4 geschreven. De PCM - chip zal nu het COMP bit zetten als het signaal sterker is - dan &H80, en het wissen als het signaal minder sterk is. - COMP wordt gelezen door met IN F,(C) register &HA5 in het F - register te lezen, waarbij bit 7 (COMP) dus de sign vlag - wordt. - - Is het signaal sterker dan &H80, dan blijft de waarde van A - ongewijzigd, was het zwakker, dan wordt bit 7 gewist. Nu - wordt bit 6 gezet. Weer wordt deze waarde naar &HA4 - geschreven om hem te vergelijken, en ook weer wordt COMP - uitgelezen via het sign bit van het vlagregister. Is het - signaal sterker, dan blijft bit 6 gezet, is het zwakker, dan - wordt bit 6 gereset. Zo wordt bit voor bit een byte PCM data - samengesteld. - - - M A X I M A L E F R E Q U E N T I E - - Deze routine is behoorlijk lang, en dat beperkt dan ook de - maximale frequentie waarmee kan worden opgenomen. Ik heb het - getest en het blijkt dat het E register een waarde moet - hebben van minimaal 10. Geeft u een lagere waarde op, dan - zal dat toch dezelfde snelheid als bij 10 worden. - - Hieronder een overzicht van een aantal mogelijke waardes van - E en de bijbehorende frequentie in kHz: - - 10 25.568 kHz - 11 23.244 kHz - 12 21.307 kHz - 13 19.668 kHz - 14 18.263 kHz - 15 17.045 kHz - 16 15.980 kHz - 17 15.040 kHz - 18 14.205 kHz - 19 13.457 kHz - 20 12.784 kHz - 21 12.175 kHz - 22 11.622 kHz - 23 11.117 kHz - 24 10.653 kHz - 25 10.227 kHz - 26 9.834 kHz - 27 9.470 kHz - 28 9.131 kHz - 29 8.817 kHz - 30 8.523 kHz - 31 8.248 kHz - 32 7.990 kHz - 33 7.748 kHz - 34 7.520 kHz - 35 7.305 kHz - 36 7.102 kHz - 37 6.910 kHz - 38 6.728 kHz - 39 6.556 kHz - 40 6.392 kHz - 41 6.236 kHz - 42 6.088 kHz - 43 5.946 kHz - 44 5.811 kHz - 45 5.682 kHz - 46 5.558 kHz - 47 5.440 kHz - 48 5.327 kHz - 49 5.218 kHz - 50 5.114 kHz - - Zoals u ziet is de maximale opneemfrequentie maar liefst - 25.568 kHz! Dat is heel wat meer dan de 15.75 kHz die met de - BIOS routines kan worden gehaald. Het afspelen kan - natuurlijk nog sneller, maar dat heeft alleen zin voor - samples die op een andere computer zijn opgenomen. - - De source PCM.ASC is op de diskette aanwezig. - - - G E I N T J E - - Een leuk geintje is tenslotte nog om de geluidstoevoer van - de turbo R aan te zetten. Pas daarbij wel op dat het geluid - niet kan gaan zingen tussen de microfoon en de luidspreker, - want dat geeft een ontzettende rotherrie. Vooral met de - ingebouwde microfoon gebeurt dat snel. Het is heel simpel, - gewoon in BASIC intypen: - - OUT &HA5,10 - - De doorvoer kan uiteraard ook weer uit, daarvoor typt u: - - OUT &HA5,8 - - Natuurlijk kunt u dit ook in ML programmeren... - - Stefan Boer diff --git a/sunrise_special/4/Print routine.md b/sunrise_special/4/Print routine.md deleted file mode 100644 index ae6a44b..0000000 --- a/sunrise_special/4/Print routine.md +++ /dev/null @@ -1,203 +0,0 @@ - P R I N T R O U T I N E - - - Met de hier volgende printroutine wordt een tekst op alle - breedten goed op het scherm gezet, voor zover dat mogelijk - is. - - - BDOS: EQU #0005 - - ;BDOS functie - StrOut: EQU 9 - - LINLEN: EQU #f3b0 ;Aantal tekens op - ;huidige scherm - - - call Print - db 2,2 ;Kantlijnen - - db "PRINTROUTINE",1 - db "============",1 - db 1 - db "Dit is een test voor mijn " - db "printroutine. " - db "Hopelijk werkt het goed.",1 - db 1 - db "De bedoeling is dat de " - db "tekst door de routine zelf goed " - db "op het scherm gezet wordt, " - db "ongeacht schermbreedte. " - db "Nu nog automatisch afbreken :-)",1 - db 1 - db "Hier begint een nieuwe alinea!",0 - rst 0 - - De routine wordt aangeroepen met de tekst achter de call. - Zo weet je precies wat er op het scherm komt te staan, en - hoef je niet met labels te werken. Om aan te geven dat een - nieuwe regel begint moet een 1 worden gebruikt, en de 0 - geeft het einde van de tekst aan. - - - ;P R I N T - ;Doel : Zet tekst op scherm - ;Input : hl: pointer naar tekst - ;Output: carry hoog: kantlijnen te groot - ;Noot : eerste 2 bytes van de tekst zijn respectievelijk - ; de rechter- en linkerkantlijn - - - Print: ex (sp),hl - - Dit zorgt ervoor dat de tekst achter de call kan staan. - - - ld a,(LINLEN) - dec a - sub (hl) - jr c,pError - - Rechterkantlijn van breedte aftrekken. Als het resultaat - kleiner dan 0 is, wordt teruggesprongen met de carry hoog. - - inc hl - sub (hl) - jr c,pError - ld (pLength),a - ld a,(hl) - inc hl - - Vervolgens wordt hetzelfde met de linkerkantlijn gedaan. De - linkerkantlijn is nog nodig om te bepalen vanaf waar de - buffer (83 tekens) moet worden beschreven. - - - push hl - ld hl,pBuffer1 - ld d,0 - ld e,a - add hl,de ;Tel linkerkantlijn - ;op bij buffer - ld (pAddress3),hl - pop hl - - pLoop1: ld a,(pLength) - ld b,a - ld de,(pAddress3) - pLoop2: ld a,(hl) - cp " " ;Spatie? - call z,pSpace - cp 1 ;Einde alinea? - jr z,pAlinea - or a ;Einde tekst? - jr z,pQuit - - Bij een spatie worden de adressen bewaard. Bij een 0 wordt - niet zomaar geRETurnd, want hl moet weer verwisseld worden - met het returnadres (dit i.v.m. tekst achter call). - - - ld (de),a - inc hl - inc de - djnz pLoop2 - - cp " " - jr z,sPrint2 - - Als het laatste teken een spatie is, hoeft er niet terug - worden gegaan naar de vorige spatie. - - - ld a,(pFlag) - or a - jr z,sPrint2 - - Als er nog geen spatie in de regel zit (pFlag wordt door de - routine pSpace gezet), kan er niet worden gekeken naar de - vorige spatie in de regel. In dit geval is de schermbreedte - te klein, en komt de tekst niet goed op het scherm. - - - xor a - ld (pFlag),a - ld hl,(pAddress1) - ld de,(pAddress2) - inc hl - sPrint2: call sPrint1 - jr pLoop1 - - pSpace: ld (pAddress1),hl - ld (pAddress2),de - ld (pFlag),a - ret - - Adressen van spatie bewaren en vlag zetten. - - - pQuit: call sPrint1 - xor a ;Carry laag - ex (sp),hl - ret - - Carry laag, want carry hoog bij terugkeer betekent een - error. - - - pAlinea: call sPrint1 - inc hl - jr pLoop1 - - Bij een nieuwe alinea moet de 1 worden overgeslagen. - - - sPrint1: push hl - ld a,13 - ld (de),a - inc de - ld a,10 - ld (de),a - inc de - ld a,"$" - ld (de),a - - Zet waarden voor einde van regel en einde van string op de - juiste adressen. - - ld de,pBuffer1 - ld c,StrOut - call BDOS - pop hl - ret - - pError: xor a ;Zoeken naar 0 - ld bc,-1 - cpir - ex (sp),hl - scf - ret - - bc wordt op -1 gezet om het hele geheugen te doorzoeken - naar de 0. scf is nog om de carry weer hoog te zetten. cpir - zet de carry namelijk weer laag. - - - ;Data - - pBuffer1: ds 79+3," " ;Buffer voor regel - pAddress1: dw pBuffer1 - pAddress2: dw 0 - pAddress3: dw pBuffer1 ;Buffer + - ;linkerkantlijn - pFlag: db 0 ;Vlag voor spatie - ;in regel - pLength: db 80 - - - De buffer is 79+3 omdat een regel in principe 80-1 - karakters lang kan zijn, en 3 bytes nodig zijn om return en - het einde van de string aan te duiden. - - Kasper Souren diff --git a/sunrise_special/4/R800 Drive.md b/sunrise_special/4/R800 Drive.md deleted file mode 100644 index f3fedbd..0000000 --- a/sunrise_special/4/R800 Drive.md +++ /dev/null @@ -1,34 +0,0 @@ - R 8 0 0 D R I V E - - - Dit programma van XelaSoft heeft ongeveer hetzelfde effect - als mijn Fastdrive, die op Sunrise Magazine #6 stond. Alleen - kun je met R800 drive nog bepalen bij welke drives wordt - teruggeschakeld. - - - L E D 'J E - - Het programma werkte eerste niet op mijn FS-A1ST, maar ik - heb dat even aangepast. Ook heb ik het zo gemaakt, dat je - ook kunt zien wanneer de Z80 mode wordt aangeschakeld. Dat - geeft mij een veiliger gevoel (nee, het is niet - vergelijkbaar met OB). - - - T E R U G S C H A K E L E N - - Het terugschakelen moet gebeuren bij de gewone diskdrive �n, - als je een MAK interface hebt, bij de harddisk. De MK en HSH - SCSI interfaces kunnen de snelheid van de R800 wel gewoon - aan. - - Het enige nadeel van dit programma t.o.v. mijn Fastdrive is - dat het vanuit BASIC moet worden opgestart. Dat komt omdat - het een stuk geheugen moet reserveren. - - De source staat ook op disk, dit om te laten zien hoe je - TSR's onder MSX-DOS 2 kunt maken, zonder MemMan te - gebruiken. - - Kasper Souren diff --git a/sunrise_special/4/Read to kana.md b/sunrise_special/4/Read to kana.md deleted file mode 100644 index ca1d064..0000000 --- a/sunrise_special/4/Read to kana.md +++ /dev/null @@ -1,20 +0,0 @@ - R E A D T O K A N A - - - Dit programma is door Erik Maas geschreven om het Kanji - gedeelte van de DRAM toch nog nuttig te kunnen gebruiken (de - studenten Japans onder ons kunnen dus alvast op ESC - drukken). - - Het laadt een file die op #4000 moet komen te staan in over - de DRAM page van de Kanji. Erik noemt het de KANA page, maar - ja, het maakt niet veel uit hoe je het noemt, veel nut(h) - heeft deze page toch niet. - - Het kan echter wel handig zijn om KUN-BASIC, of andere - programma's die CALL's mogelijk maken, erin te zetten. - Misschien kan ook WBASS2 erin worden gezet, maar dit moeten - degenen die dit programma veelvuldig gebruiken zelf maar - uitzoeken. - - Kasper Souren diff --git a/sunrise_special/4/Tweede drive aan turbo r.md b/sunrise_special/4/Tweede drive aan turbo r.md deleted file mode 100644 index 1a37757..0000000 --- a/sunrise_special/4/Tweede drive aan turbo r.md +++ /dev/null @@ -1,36 +0,0 @@ - T W E E D E D R I V E A A N T U R B O R - - - Op de turbo R (FS-A1ST en FS-A1GT) zit normaal geen - drive-aansluiting. Met onderstaande gegevens is dat echter - simpel zelf te maken. - - - Printaan- 15 pens 34 pens - sluiting: sub-d: shugart: - - +5 volt : pen 1 pen 1 voedingsplug - Ground : pen 7 pen 2 voedingsplug - Ready : pen 6 pen 3 pen 34 - Side select : pen 9 pen 4 pen 32 - Read data : pen 11 pen 5 pen 30 - Write protected: pen 12 pen 6 pen 28 - Track 0 : pen 13 pen 7 pen 26 - Write gate : pen 14 pen 8 pen 24 - Write data : pen 16 pen 9 pen 22 - Step : pen 18 pen 10 pen 20 - Direction : pen 19 pen 11 pen 18 - Motor on : pen 20 pen 12 pen 16 - Drive select : pen 22 pen 13 pen 10 - Index : pen 23 pen 14 pen 8 - Disk change : pen 24 pen 15 pen 2 - - Drive instellen als DS0!! - - - D I S C L A I M E R - - Stichting Sunrise is NIET aansprakelijk voor eventuele - schade aan mens en/of machine door uitvoering van dit - project. - \ No newline at end of file diff --git a/sunrise_special/4/V9990 Specificaties.md b/sunrise_special/4/V9990 Specificaties.md deleted file mode 100644 index 199247a..0000000 --- a/sunrise_special/4/V9990 Specificaties.md +++ /dev/null @@ -1,128 +0,0 @@ - V 9 9 9 0 S P E C I F I C A T I E S - - - P A T T E R N M O D E - - M O D E P 1 P 2 - ----------------------------------------------------------- - resolutie 32 x 26.5 64 x 26.5 - (256 x 212) (512 x 212) - aantal schermen 2 1 - karakter grootte 8 x 8 8 x 8 - aantal kleuren 15 + transp. 15 + transparant - palette 4 tabellen 4 tabellen - met 16 kleuren met 16 kleuren - uit 32768 uit 32768 - image space 64 x 64 128 x 64 - aantal patronen max. 16384 max. 16384 - - - S P R I T E S - - ------------------------------------------------------------ - grootte 16 x 16 - aantal sprites 125 op 1 scherm - 16 op 1 beeldlijn - aantal kleuren 15 + transparant voor elke pixel - elke sprite kan een eigen palette hebben - (1 van de 4!) - aantal patronen Je hebt 256 patronen, deze zou je volgens - het databoek ook samen kunnen laten vallen - met het "normale" scherm, om delen daarvan - als sprite te kunnen gebruiken; handig. - prioriteit Voor elke sprite kun je aangeven of deze - voor of achter het "normale" scherm moet - komen (kun je sprites ACHTER iets door laten - gaan i.p.v. er altijd voor laten hangen). - Als sprites elkaar overlappen, heeft het - laagste spritenummer voorrang. - ------------------------------------------------------------ - - - B I T M A P M O D E - - mode resolutie bits/dot - ------------------------------------------- - B1 256 x 212 16 - (256 x 424) 8 - 4 - 2 - B2 384 x 240 16 (256 kB nodig) - (384 x 480) 8 - 4 - 2 - B3 512 x 212 16 (256 kB nodig) - (512 x 424) 8 - 4 - 2 - B4 768 x 240 4 - (768 x 480) 2 - B5 640 x 400 4 (256 kB nodig) - 2 - B6 640 x 480 4 (256 kB nodig) - 2 - ------------------------------------------- - - In de eerste kolom staat de resolutie van het scherm, non - interlaced, en tussen haakjes de resolutie interlaced (er - zijn modes die niet interlaced kunnen worden weergegeven). - In de tweede kolom staat het aantal bit's wat er per pixel - (dot) gebruikt wordt. Ik vermeld niet het aantal kleuren, - want dat hangt af van welke mode (YJK, RGB of YUV) je - daarvoor gebruikt. - - Voorbeeld: 4 bits per dot is 2^4 = 16 kleuren, als je kiest - voor palette mode 0, betekent dat dat je 16 kleuren kunt - kiezen uit de 32768 mogelijke. - - Elk scherm is in feite een gedeelte van een Image, deze kan - groter zijn dan het scherm, bv. 2048 bij 1024 pixels. Wat - heb je daaraan, zul je denken, maar het is eigenlijk een - groot scherm, waarvan je een deel op je monitor plaatst. Je - kunt elk willekeurig gedeelte van de Image eruit lichten, - wat een omnidirectionele scroll geeft (zegt de handleiding - dus). Dit is niet alleen makkelijk voor spellen, maar ook - zeer handig voor DTP toepassingen. - - - P A L E T T E M O D E S - - bit/dot PLTM conversie methode aantal kleuren - ----------------------------------------------------------- - 16 0 RGB (!YS:1,G:5,R:5,B:5) 32768 - - 8 0 Palette 64 van de 32768 - 1 RGB (G:3, R:3, B:2) 256 - 2 YJK 19268 - 3 YUV 19268 - - 4 0 Palette 16 van de 32768 - - 2 0 Palette 4 van de 32768 - ----------------------------------------------------------- - - Je kunt bij elke display mode een palette mode kiezen, mits - het aantal bits per dot maar overeenkomen. Hieronder even de - uitleg van de tabel. - - Bit/dot : aantal bits dat er per pixel gebruikt wordt. - PLTM : manier van decoderen van kleuren, hoogste 2 bits - van register 13. - RGB : hierbij staat de RGB waarde in het geheugen, in de - tabel staat hoeveel bits er voor welke kleur wordt - gebruikt. (Bijv. SCREEN 8 bij de V9958.) - En dan nog een extra : het !YS bit, deze bepaalt - PER pixel of het bv. transparant is, en zo kan - worden gebruikt voor Super Impose. - Palette : in het geheugen staat een kleur nummer die zelf - een RGB waarde heeft, gekozen met het palette. - (Bijv. SCREEN 5.) - YJK : zelfde methode als SCREEN 12 - YUV : hiervan weet ik niet hoe het werkt, maar het zal - veel op YJK lijken - - Deze gegevens heb ik allemaal uit het V9990 aplication - manual. - - Erik Maas - \ No newline at end of file diff --git a/sunrise_special/4/VDP Cursus 5.md b/sunrise_special/4/VDP Cursus 5.md deleted file mode 100644 index af4e05e..0000000 --- a/sunrise_special/4/VDP Cursus 5.md +++ /dev/null @@ -1,166 +0,0 @@ - M S X 2 / 2 + V D P C U R S U S ( 5 ) - - - In dit vijfde deel worden de statusregisters behandeld. De - naam zegt het al, deze registers geven informatie over de - status van de Video Display Processor. Uiteraard kunnen - statusregisters alleen gelezen worden en niet beschreven. - - Het lezen van een statusregister is in deel 1 (Sunrise - Special #2) behandeld, daar kunt u dat nog eens nalezen. - - - O V E R Z I C H T S T A T U S R E G I S T E R S - - MSB 7 6 5 4 3 2 1 0 LSB - S#0 F 5S C ---vijfde sprite--- Status #0 - - F: Vertical scanning interrupt flag - Wordt geset als de VDP bovenaan het scherm begint - met de beeldopbouw. F wordt gereset als S#0 wordt - gelezen. Dit is de normale interrupt, die behalve - naar de hook &HFD9A ook naar de hook &HFD9F springt. - 5S: Flag voor de vijfde/negende sprite - Deze vlag geeft aan dat er meer sprites op een hori- - zontale lijn voorkomen dan de VDP kan weergeven. In - G3 (SCREEN 4) en hoger zijn dat er acht, in de ande- - re schermen vier. - C: Collision flag - Wordt gezet als twee sprites elkaar raken. - vijfde - sprite: Bevat het nummer van de vijfde of negende sprite. - - - MSB 7 6 5 4 3 2 1 0 LSB - S#1 FL LPS -Identification #- FH Status #1 - - FL: Lightpen flag (Lightpen flag is geset, LP bit 6 R#8) - Als de lichtpen licht waarneemt moeten zowel dit bit - als IE2 (bit 5 van R#0) geset zijn om een interrupt - te veroorzaken. FL wordt gereset als S#1 wordt - gelezen. - - Mouse Switch 2 (Mouse flag is geset, MS bit 7 R#8) - De 2e vuurknop van de muis is ingedrukt. FL wordt - niet gereset als S#1 wordt gelezen. - - LPS: Lightpen switch (Lightpen flag is geset) - De vuurknop van de lichtpen is ingedrukt. LPS wordt - niet gereset als S#1 wordt gelezen. - - Mouse switch 1 (Mouse flag set) - De 1e vuurknop van de muis is ingedrukt. LPS wordt - niet gereset als S#1 wordt gelezen. - - Identification number: - Het ID# van de VDP. Hieraan kun je zien of het V9938 - of V9958 is (bit 2 van S#1 is geset als V9958). - - FH: Horizontal scanning interrupt flag - FH wordt geset als een zgn. line-interrupt optreedt, - dus als de VDP begint met het weergeven van de lijn - die in R#19 staat. Er wordt een interrupt - gegenereerd als IE1 (bit 4 van R#0) is geset. FH - wordt gereset als S#1 wordt gelezen. - - Let op: de lichtpen- en muisuitlezing wordt bij de V9958 - niet meer door de VDP gedaan. De bits FL en LPS hebben dus - hun betekenis verloren. Bij MSX2 wordt het uitlezen van de - muis overigens ook al niet met de VDP gedaan. - - - MSB 7 6 5 4 3 2 1 0 LSB - S#2 TR VR HR BD 1 1 EO CE Status #2 - - TR: Transfer ready flag - Als de CPU (microprocessor) data naar de VDP stuurt, - moet er gewacht worden tot dit bit geset is. Dan mag - de data verstuurd worden. - - VR: Vertical scanning line timing flag - Tijdens verticaal scannen is deze flag geset. - - HR: Horizontal scanning line timing flag - Tijdens horizontaal scannen is deze flag geset. - - BD: Boundary color detect flag - Bij het Search commando (zie VDP cursus deel 4) - geeft deze flag aan of de randkleur is gevonden of - niet. - - EO: Display field flag - Geeft bij het afwisselend weergeven van pagina's aan - welke pagina er wordt weergegeven. - - CE: Command execute flag - Geeft aan dat een commando wordt uitgevoerd. Wacht - tot dit bit gereset is voordat het volgende commando - naar de VDP wordt gestuurd. Zie VDP cursus deel 3 en - 4. - - - MSB 7 6 5 4 3 2 1 0 LSB - S#3 X7 X6 X5 X4 X3 X2 X1 X0 Column low - S#4 1 1 1 1 1 1 1 X8 Column high - S#5 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 Row low - S#6 1 1 1 1 1 1 Y9 Y8 Row high - - Bovenstaande registers worden gebruikt voor het aangeven van - de de plaats van de spritebotsing, de plaats van de lichtpen - of de relatieve beweging van de muis. Zie voor de - spritebotsing verderop. Lichtpen en muis worden niet via de - VDP uitgelezen. - - - MSB 7 6 5 4 3 2 1 0 LSB - S#7 C7 C6 C5 C4 C3 C2 C1 C0 Color reg - - Dit register wordt gebruikt bij de POINT en VRAM to CPU - commando's. De VRAM data staat in dit register. (Zie VDP - cursus deel 4). - - MSB 7 6 5 4 3 2 1 0 LSB - S#8 BX7 BX6 BX5 BX4 BX3 BX2 BX1 BX0 Border X low - S#9 1 1 1 1 1 1 1 BX8 Border X hig - - De X co�rdinaat die wordt gevonden bij het Search commando - wordt in deze registers gezet. (Zie VDP cursus deel 4). - - Nu we de theorie hebben behandeld komen er nog een aantal - toepassingen aan bod. - - - S P R I T E B O T S I N G - - Bij een spritebotsing wordt C (bit 5 van S#0) geset. Als - zowel MS als LP (bit 7 en 6 van R#8) zijn gereset, dan - zullen de co�rdinaten van de botsing naar S#3 t/m S#6 worden - geschreven. Let op: bij het lezen van S#5 wordt de inhoud - van S#3 t/m S#6 gereset. - - De X die in S#4 en S#3 staat is 12 meer dan de X van de - botsing, de Y die in S#5 en S#6 staat is 8 meer dan de - botsing. Oftewel: - - XS#3S#4 = XBOTSING + 12 - YS#5S#6 = YBOTSING + 8 - - - S C R E E N S P L I T - - Het is met de statusregisters zeer eenvoudig om een - nauwkeurige screensplit te maken. We gebruiken daarvoor HR - en FH. Eerst zetten we de lijn waarop de split moet optreden - in R#19. Vervolgens wachten we tot FH (bit 7 van S#1) wordt - gezet. Nu kunnen we de screensplit strak tegen de border - krijgen door HR uit te lezen. Als HR (bit 5 van S#2) is - geset begint de VDP met het weergeven van een nieuwe lijn. - Voer nu zo snel mogelijk de nodige akties uit, en de - screensplit is nagenoeg perfect. - - Een korte aflevering dit keer. De sprites en de - beeldschermopslag komen nog aan bod, daarna gaan we verder - met de toepassingen. De volgende keer neem ik u mee naar de - wereld van de sprites. - - Stefan Boer diff --git a/sunrise_special/4/VDP Curus 6.md b/sunrise_special/4/VDP Curus 6.md deleted file mode 100644 index 4297213..0000000 --- a/sunrise_special/4/VDP Curus 6.md +++ /dev/null @@ -1,358 +0,0 @@ - M S X 2 / 2 + V D P C U R S U S ( 6 ) - - - Zoals beloofd ga ik het deze keer hebben over sprites. - Voordat ik begin met het behandelen van de echte sprites, - wil ik eerst nog even een misverstand uit de wereld helpen. - - - S O F T W A R E S P R I T E S - - Misschien heeft u deze term wel eens gehoord of er iets over - gelezen. De doorsnee MSX'er weet wel dat er sprites bestaan, - maar dat er verschil zou zijn tussen softwaresprites en - hardwaresprites gaat de meesten boven de pet. En dat is ook - niet zo vreemd, want er bestaat maar ��n soort sprites op - MSX, de hardwaresprites. Voor alle duidelijkheid: dit zijn - de sprites die je in BASIC aanstuurt met PUT SPRITE en - SPRITE$. - - Wat zijn die softwaresprites dan wel? Dat zijn gewoon - plaatjes die gekopieerd worden. Die plaatjes staan dan op - een onzichtbare page en worden met een razendsnelle COPY - opdracht naar de zichtbare pagina gekopieerd. (Hoewel ik - hier spreek van 'razendsnel', betekent dat niet dat er een - HMMM (High-speed Move vraM to vraM) wordt gebruikt, dan kan - er geen TPSET worden gebruikt en dat is noodzakelijk bij - softwaresprites. Er wordt LMMM (Logical Move vraM to vraM) - gebruikt.) - - Softwaresprites hebben het voordeel dat het kleurgebruik - (zeker op SCREEN 8, op SCREEN 10 t/m 12 zijn softwaresprites - bijna onmogelijk) onbeperkt is, en dat ze in theorie elke - grootte kunnen hebben. In praktijk kunnen ze natuurlijk niet - te groot zijn, want dan duurt het kopi�ren zo lang dat het - niet meer mooi is. Uiteraard kunnen op de snelheidsduivel - turbo R grotere softwaresprites worden gebruikt, kijk maar - naar Seed of Dragon. - - De nadelen zijn ook niet mis: het is trager dan - softwaresprites, moeilijker aan te sturen (je moet alles - zelf doen) en het neemt meer VRAM in beslag. Bovendien is er - nog een probleem: als de softwaresprite zich verplaats moet - het VRAM dat eronder zat weer worden hersteld, dat is bij - gewone sprites niet nodig. - - Een ander voordeel van softwaresprites is nog dat er geen - maximum aantal sprites is en dat ze nooit kunnen gaan - knipperen, maar omdat deze problemen alleen bij grote - aantallen sprites voorkomen en de softwaresprites dan veel - te langzaam worden is dat niet zo'n groot voordeel. - - Hardwaresprites hebben tenslotte nog het voordeel dat je ze - heel makkelijk stil kunt laten staan terwijl je de rest van - het scherm laat scrollen (of dat nu hardwarematig (R#23 - verticaal / R#26 + R#27 horizontaal) of softwarematig (met - COPY) gaat). Softwaresprites zou je dan elke keer moeten - verplaatsen. - - De softwaresprites zullen behandeld worden bij de - toepassingen, die later in de cursus veelvuldig aan bod - zullen komen. Ik ben behoorlijk afgedwaald, laten we nu maar - beginnen met het onderwerp van deze keer: (hardware)sprites. - - - S P R I T E M O D E 2 - - Ik behandel hier alleen de zgn. SPRITE MODE 2, die in SCREEN - 4 en hoger wordt gebruikt. Dit is tenslotte een MSX2/2+ VDP - cursus, dus de MSX1 sprites slaan we over. - - Er zijn 32 sprites, genummerd van #0 tot en met #31. Een - sprite met een lager nummer heeft een hogere prioriteit. Er - kunnen maximaal 8 sprites op een horizontale lijn worden - getoond. Zijn er meer dan 8 sprites op een horizontale lijn, - dan worden de lijnen van de sprites met de laagste - prioriteit niet getoond. Het kan dus bijvoorbeeld gebeuren - dat een sprite voor de helft wegvalt. - - Als de ingekleurde delen van twee sprites elkaar raken - (botsen), zal bit 5 van S#0 worden geset. De co�rdinaten van - de botsing zullen in S#3 t/m S#6 worden gezet (zie VDP - cursus deel 5). - - Als er negen of meer sprites op een horizontale lijn staan, - dan zal bit 6 van S#0 worden geset. Bit 0-4 van S#0 zullen - dan het nummer bevatten van de negende sprite. - - Elke horizontale lijn van een sprite mag een eigen kleur - hebben uit het palet van 16 kleuren. - - De sprite prioriteiten kunnen worden uitgezet door het CC - bit van een lijn te setten (zie verderop), de overlappende - gedeeltes van twee sprites worden dan geORd. - - - S P R I T E R E G I S T E R S - - De grootte van de sprite wordt bepaald door bit 1 van R#1. - - MSB 7 6 5 4 3 2 1 0 LSB - R#1 0 BL IE0 M1 M2 0 SI MAG Mode reg. #1 - - SI = 1 : 16 x 16 pixels - SI = 0 : 8 x 8 pixels - - De sprite kan op normaal formaat of vier maal zo groot - worden weergegeven. Dit wordt bepaald door bit 0 van R#1. - - MAG = 1 : vergroot - MAG = 0 : normaal - - Met bit 1 van R#8 kan worden bepaald of de sprites aanstaan. - Als er geen sprites worden gebruikt, zet ze dan uit want dan - werkt de VDP sneller (meet het maar eens na, het scheelt - behoorlijk!). - - MSB 7 6 5 4 3 2 1 0 LSB - R#8 MS LP TP CB VR 0 SPD BW Mode reg. #2 - - SPD = 1 : disable sprites (zet sprites uit) - SPD = 0 : enable sprites (zet sprites aan) - - De vorm van de sprite staat in de Sprite Pattern Generator - Table. Er kunnen 256 patronen worden opgeslagen van elk 8 - bytes lang (#0 t/m #255). Het beginadres van een patroon is - als volgt te berekenen: - - + * 8 - - De kleuren van een sprite staan in de Sprite Color Table. - Behalve de kleuren worden er ook drie attribuutbits per lijn - opgeslagen. 8x8 sprites vergen 8 bytes, 16x16 sprites 16 - bytes. Het beginadres van de kleurinfo van een sprite is als - volgt te berekenen: (er is 1 positie per sprite, #0 t/m #31) - - + * 16 - - De overige attributen (coordinaten en patroonnummer) staan - in de Sprite Attribute Table, 4 bytes per sprite (#0 t/m - #31). Het beginadres van de attributen van een sprite is als - volgt te berekenen: - - + * 4 - - N.B. al deze tabellen staan in het VRAM. - - - S P R I T E A T T R I B U T E T A B L E - - Op + 0 staat de Y-co�rdinaat, 0 t/m 255. Is de - Y coordinaat gelijk aan 216, dan worden alle sprites met een - lagere prioriteit niet getoond, inclusief de sprite zelf. - Let op: de bovenste lijn van de sprite komt ��n lijn lager - dan de hier opgegeven y-co�rdinaat. - - Op + 1 staat de X-co�rdinaat, van 0 t/m 255. - Let op: ook in SCREEN 6 en 7 wordt de horizontale as voor - sprites in 256 stapjes verdeeld, en niet in 512! - - Op + 2 staat het patroonnummer. Hiermee wordt - aangegeven welk patroon uit de Sprite Pattern Generator - Table moet worden genomen. Let op: als de sprite grootte - 16x16 is, dan worden er vier patronen genomen voor ��n - sprite. Het maakt dan niet uit welke van de vier nummers je - opgeeft. Er zijn dus in feite maar 64 patronen bij 16x16 - sprites. - - MSB 7 6 5 4 3 2 1 0 LSB - R#5 A14 A13 A12 A11 A10 A9 1 1 Sprite attr. tab. - R#11 0 0 0 0 0 0 A16 A15 base adress reg. - - Het beginadres van de attribuuttabel is hier opgeslagen. Let - op: bit A9 is altijd 1. Door deze registers te manipuleren - is het mogelijk om de informatie van meer dan 32 sprites in - het VRAM op te slaan of om bijvoorbeeld PAGE 0 te tonen - terwijl de attribuuttabel ergens in PAGE 2 staat. - - - P A T T E R N G E N E R A T O R T A B L E - - In deze tabel staan de bit-matrices die de vorm van de - sprites bepalen. Het werkt heel simpel; 0 staat voor uit en - 1 voor aan. Een spookje uit Pacman zou er bijvoorbeeld zo - uit kunnen zien: - - &B00111100 - &B01111110 - &B11011011 - &B11011011 - &B11111111 - &B11111111 - &B11011011 - &B11011011 - - Voor elk patroon worden 8 bytes gebruikt. Er zijn totaal 256 - patronen, genummerd van #0 t/m #255. Bij 8x8 sprites krijgt - elke sprite ��n patroon, een 16x16 sprite krijgt er vier. - - MSB 7 6 5 4 3 2 1 0 LSB - R#6 0 0 A16 A15 A14 A13 A12 A11 Sprite patt. tab. - - Hier is het beginadres van de tabel opgeslagen. Door het - manipuleren met dit register kunnen bijvoorbeeld veel meer - dan 256 patronen gelijktijdig in het VRAM worden gezet, etc. - - - S P R I T E C O L O R T A B L E - - Elke horizontale lijn kan zijn eigen kleur krijgen (kleur 0 - is altijd transparant). Bovendien kunnen per lijn de sprite - prioriteit, de botsingsdetectie en de 'early clock' worden - aan- of uitgezet. - - Het beginadres van deze tabel ligt altijd precies 512 bytes - onder het beginadres van de Sprite Attribute Table. Per - Sprite (32 stuks, #0 t/m #31) worden er 16 bytes - gebruikt. Dat maakt totaal 512 bytes. Elke byte is als volgt - opgebouwd: - - MSB 7 6 5 4 3 2 1 0 LSB - EC CC IC 0 ----kleur------ - - EC: Early Clock, 1: verschuif lijn 32 bits naar links - CC: Priority Enable, 1: OR kleuren als sprites - overlappen - IC: Collision Detect, 1: negeer botsingen - - Bij CC=1 worden ook de botsingen niet gedetecteerd. - - - S P R I T E P R I O R I T E I T - - De sprite prioriteit wordt uitgezet als het CC-bit gelijk is - aan 1. De lijnen van een sprite waarvan CC gelijk is aan 1 - worden alleen getoond als er op diezelfde horizontale lijn - een sprite met een lager spritenummer voorkomt. - - Dit kan ook worden gebruikt om extra kleuren te cre�ren in - een samengestelde sprite (een 'sprite' die uit een aantal - afzonderlijke sprites is opgebouwd). Bijvoorbeeld: - - 888888-- ----4444 8888CC44 - 888888-- ----4444 8888CC44 - 888888-- + -------- = 888888-- - 888888-- 11------ 998888-- - 888888-- 11------ 998888-- - --222222 11------ 11222222 - -2222222 11------ 13222222 - 22222222 11------ 33222222 - - Op deze manier is het dus vrij eenvoudig om op een lijn drie - verschillende kleuren te krijgen, terwijl je maar twee - sprites gebruikt. - - - S P R I T E B O T S I N G - - Dit hebben we ook al bij de statusregisters behandeld, maar - voor de overzichtelijkheid behandelen we het nog maar een - keer. - - Als CC gelijk is aan 0 en gedeeltes van een sprite die geen - kleur 0 hebben overlappen elkaar, dan wordt er een sprite - botsing gedetecteerd. Bit 5 van S#0 wordt dan geset. Dit bit - wordt weer gereset als S#0 wordt gelezen. - - MSB 7 6 5 4 3 2 1 0 LSB - S#0 F 9S C ----9th sprite #--- Status reg. #0 - - C = collision, 9S = negen sprites/regel, 9th sprite # = - nummer van negende sprite. - - Als MS en LP niet geset zijn (R#8, muis en lichtpen, bij - V9958 niet aanwezig), dan worden de co�rdinaten van de - botsing in de statusregisters S#3 t/m S#6 gezet: - - MSB 7 6 5 4 3 2 1 0 LSB - S#3 X7 X6 X5 X4 X3 X2 X1 X0 Status reg. #3 - S#4 1 1 1 1 1 1 1 X8 Status reg. #4 - S#5 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 Status reg. #5 - S#6 1 1 1 1 1 1 1 Y8 Status reg. #6 - - Van de X co�rdinaat moet nog 12 worden afgetrokken en van de - Y co�rdinaat 8. - - - S P R I T E K L E U R E N - - In SCREEN 5, 7, 10, 11 en 12 zijn de kleuren van de sprites - gelijk aan de kleuren uit het palet. In SCREEN 8 worden - andere kleuren gebruikt: - - Kleurcode: Groen: Rood: Blauw: - ---------------------------------------------------- - 0 0 0 0 transparant - 1 0 0 2 d. blauw - 2 0 3 0 d. rood - 3 0 3 2 d. magenta - 4 3 0 0 groen - 5 3 0 2 blauw/grijs - 6 3 3 0 oker - 7 3 3 2 grijs - 8 8 7 2 zalmrose - 9 0 0 7 blauw - 10 0 7 0 rood - 11 0 7 7 magenta - 12 7 0 0 l. groen - 13 7 0 7 cyaan - 14 7 7 0 geel - 15 7 7 7 wit - ---------------------------------------------------- - - SCREEN 6 is ook een speciaal geval, omdat er dan maar vier - kleuren zijn. Die kleuren worden ook in de sprites gebruikt - en het palet kan aangepast worden. Je kunt hier 'gestreepte' - sprites maken. De kleurcode wordt als volgt geinterpreteerd: - - MSB 3 2 1 0 LSB - -even-- -oneven Kleurcode (0-15) - - De bovenste twee bits worden gebruikt voor de kleur van de - oneven pixels en in de onderste twee bits staat de kleur van - de oneven pixels. Beide kleuren kunnen liggen tussen 0 en 3. - - - T P E N S P R I T E S - - Bit 5 van R#8 (TP) geeft aan of kleur 0 transparant is of - dat kleur 0 gewoon als paletkleur kan worden gebruikt. In - samenhang met sprites zijn er twee situaties: - - TP=0: (gedeeltes van) sprites met kleurcode 0 worden niet - getoond, op die plaats kan dan ook geen botsing worden - gedetecteerd. - - TP=1: (gedeelte) van sprite met kleurcode 0 wordt wel - getoond, volgens de paletkleur (in SCREEN 8 altijd zwart), - spritebotsingen worden normaal gedetecteerd. - - - T O T S L O T - - Voor het aansturen van sprites is schrijven naar het VRAM - noodzakelijk. Lees de procedures daarvoor nog maar eens na - in deel 1 van de cursus. Het geeft bijvoorbeeld een enorme - snelheidswinst om eerst de VDP klaar te zetten voor het - schrijven van data vanaf een bepaald adres, en vervolgens de - data rechtstreeks naar Port #0 (port &H98) te sturen. Bij - sprites moeten er toch vaak achterelkaar liggende adressen - worden beschreven. - - Waarschijnlijk zal er in VDP Cursus deel 15 (die komt op - Sunrise Magazine #10) een routine met sprites worden - behandeld. - - Veel succes met sprites op MSX en tot de volgende keer. - - Stefan Boer diff --git a/sunrise_special/4/Werken met ASCII C deel 2.md b/sunrise_special/4/Werken met ASCII C deel 2.md deleted file mode 100644 index bb518ad..0000000 --- a/sunrise_special/4/Werken met ASCII C deel 2.md +++ /dev/null @@ -1,346 +0,0 @@ - H E T W E R K E N M E T A S C I I C - - - - D E E L 2 - - C M E T A S S E M B L E R - - Hoewel ASCII C behoorlijk goede machinecode genereert, is - het soms toch handig om bepaalde routines in assembler te - schrijven. Zo is het bijvoorbeeld niet mogelijk om direct de - BIOS aan te roepen, hier is toch weer een library functie - voor nodig. Ook VDP I/O kan het beste in assembler worden - gedaan, omdat dit toch een stuk sneller gaat. - - Gelukkig is dit met ASCII C geen enkel probleem, het is - namelijk mogelijk om een library in assembler te schrijven - en de functies die in deze library staan, vervolgens te - gebruiken vanuit een C programma. - - Als de library goed wordt opgezet is het zelfs mogelijk om - uit 1 enkele source file zowel de .TCO file voor de - parameter checker te maken, als de .REL file voor de linker. - - In dit deel van de cursus zullen achtereenvolgens de - volgende onderwerpen worden besproken: - - - Het doorgeven van variabelen aan de functies. - - Het opzetten van de source zodat er zowel een .TCO als - een .REL file van gemaakt kan worden. - - Een voorbeeld library. - - - V A R I A B E L E N D O O R G E V E N - - ASCII-C kent 2 typen functies: - - - Fixed parameter functies: de functie heeft een vast aantal - parameters. - - Variabele parameter functies: de functie heeft een - variabel aantal parameters. - - Normaal gaat de C-compiler er uit dat een functie van het - fixed parameter type is. Een variabele parameter functie - moet eerst als volgt gedeclareerd worden: - - int func(.); - - Bij een fixed parameter functie worden de eerste 3 - variabelen in de Z80 registers doorgegeven, de rest wordt - allemaal op de stack gezet. Hierbij wordt de volgende - conventie gebruikt: - - parameter | char | niet-char - -----------+--------+--------------- - 1e | A | HL - 2e | E | DE - 3e | C | BC - 4e | (SP+2) | (SP+2, SP+3) - 5e | (SP+4) | (SP+4, SP+5) - etc. - - Bij een variabele parameter functie wordt het aantal - variabelen in HL gezet, en de rest wordt op de stack - gepushed. De volgorde is hierbij weer hetzelfde als bij een - fixed parameterfunctie, dus de variabelen worden als volgt - doorgegeven: - - parameter | char | niet-char - -----------+--------+--------------- - aantal vars| HL | HL - 1e | (SP+2) | (SP+2, SP+3) - 2e | (SP+4) | (SP+4, SP+5) etc. - - Als de functie een bepaalde waarde berekent, dan moet deze - ook weer worden teruggegeven aan de aanroepende functie, dit - gaat altijd via de registers. Als het functie type char is, - dan wordt de waarde teruggegeven in de A en in het andere - geval komt ze terug in HL. - - Een functie mag in principe alle registers veranderen. - - Voorbeeld: - - Stel je wilt een functie schrijven die aan karakter afdrukt - via de MSX1 main rom (CHPUT: adres 00A2H), en een functie - die een karakter van het toetsenbord leest (CHGET: adres - 009FH). Je zult deze functies dan moeten declareren in het C - programma dat er gebruik van gaat maken. Om dit te bereiken - kun je het beste alle declaraties die nodig zijn voor je - library bij elkaar zetten in 1 header file die je dan - include vanuit je C programma's. In deze header file moeten - dan de volgende declaraties staan: - - void bchput(); /* zet karakter via bios op scherm */ - char bchget(); /* lees karakter uit via bios */ - - In de assembly source (mlvb1.mac) zet je vervolgens de - volgende routines: - - bchput:: ld ix,0a2h ;Druk karakter in A - jr domsx1 ; af via de BIOS - - bchget:: ld ix,09fh ;Lees een karakter - domsx1: ld iy,(0fcc0h) ; en zet dat in A - jp 01ch - - end - - - Deze source kun je assembleren met: - - M80 = MLVB1 /Z - - om het bestand MLVB1.REL te maken. - - In een C programma (CVB1.C) kun je ze dan als volgt - gebruiken: - - typedef char void; - - void bchput(); - char bchget(); - - void main() - { - char test; - - do { - test = bchget(); /* Lees karakter uit via bios */ - bchput(test); - } while (test != 13); - } - - Deze listing kun je vervolgens compileren, assembleren en - linken met: - - CF CVB1 - CG -K CVB1 - M80 = CVB1 /Z - L80 CVB1,MLVB1,CVB1/N/Y/E:MAIN@ - - Als je dit allemaal hebt gedaan, dan heb je nu een (klein) - programma met de naam CVB1.COM, waarmee je kunt typen tot je - op de return toets duwt. - - - Z O W E L . T C O A L S . R E L V E R S I E - - V A N E E N S O U R C E - - Zoals je in bovenstaand voorbeeld wel kunt zien is het niet - zoveel werk om C te combineren met assembler. Het wordt - echter iets meer werk als je de library netter wilt - opzetten. - - In het bovenstaande voorbeeld kun je bijvoorbeeld geen - gebruik maken van de functie parameter checker (FPC) om te - kijken of het type van de variabelen wel klopt. - - Ook de linker wordt nu niet optimaal benut. Met L80 is het - namelijk mogelijk om een library zo samen te stellen dat - alleen functies die gebruikt worden, ook worden meegelinkt. - - Om dit te bereiken moet de source echter worden opgesplitst - in allemaal losse sources (��n source per onafhankelijke - functie). Deze sources moeten vervolgens allemaal los - geassembleerd worden (zodat er allemaal losse .REL files - ontstaan), en deze .REL files kunnen dan met LIB80 aan - elkaar worden gekoppeld tot 1 grote library. - - Om nu te voorkomen dat je disk vol komt te staan met - honderden losse library routines heeft ASCII corporation het - hulp programma MX gemaakt. Dit programma splitst 1 grote - source op in losse deel sources, maakt een batchfile aan om - deze sources afzonderlijk te assembleren en weer te deleten - en om vervolgens de .REL files te linken tot 1 .LIB file. - - Om goed gebruik te maken van MX moet de source echter wel - goed zijn opgezet. Hierbij wordt gebruik gemaakt van het - feit dat M80 een macro assembler is. In je source dien je 3 - (verder lege) macro's te defini�ren: - - module macro - endm - - endmodule macro - endm - - extrn macro - endm - - Alles wat in principe echt bij elkaar hoort kun je - vervolgens tussen MODULE FILENAME en ENDMODULE zetten. - Indien je vanuit dit stuk machinecode ook nog routines wilt - aanroepen die in een andere module staan, dan dien je deze - routines te declareren met EXTRN ROUTINE. - - MX zal dan alles wat tussen MODULE en ENDMODULE staat in het - bestand met de naam FILENAME zetten. In dit bestand worden - dan de EXTRN ROUTINE declaraties omgezet in de normale - EXTERN ROUTINE declaraties die nodig zijn voor M80. - - Het is wel belangrijk dat je de juiste volgorde aanhoudt als - bepaalde routines gebruik maken van andere routines: - - Als een routine uit MODULE A gebruik maakt van een routine - uit MODULE B, dan dient MODULE B VOOR MODULE A in de source - te staan!! - - Als we bij het bovenstaande voorbeeld blijven, dan kunnen we - de volgende source maken (met de naam MLVB2.MAC): - - module macro - endm - - endmodule macro - endm - - extrn macro - endm - - MODULE DOMSX1 - domsx1:: ld iy,(0fcc0h) - jp 01ch - ENDMODULE - - MODULE BCHPUT - extrn domsx1 ;Deze routine is nodig - bchput:: ld ix,0a2h ;Zet karakter op scherm - jp domsx1 - ENDMODULE - - MODULE BCHGET - extrn domsx1 - bchget:: ld ix,09fh ;Lees karakter uit - jp domsx1 - ENDMODULE - - end - - - Deze nieuwe source kun je nog altijd direct assembleren met - M80. Wil je er echter een library van maken waaruit alleen - de functies worden meegelinkt die aangeroepen worden, dan - dien je de volgende stappen te ondernemen: - - - Zorg ervoor dat AREL.BAT op je disk staat - - Zorg ervoor dat MX.COM, M80.COM en LIB80.COM op je disk - staan. - - Typ in: - MX -L MLVB2 > TEMP.BAT TEMP REN MLVB2.LIB MLVB2.REL - - Deze nieuwe library kun je vervolgens meelinken met: - - L80 CVB1,MLVB2/S,CVB1/N/Y/E:MAIN@ - - De /s achter mlvb2 betekent dat L80 alleen die modules moet - meelinken waar routines in zitten die worden aangeroepen. - - In het eerste C voorbeeld worden zowel bchput als bchget - gebruikt. Ze zullen in dit geval dan ook beiden worden - meegelinkt en er is nu dus geen echt voordeel behaald. In - het volgende voorbeeld is het gebruik van de (lastigere) - methode via MX wel al voordeliger (CVB2.C): - - typedef char void; - void bchput(); - - void bputstr(string) - char *string; - { - while (*string) - bchput(*string++); - } - - void main() - { - bputstr("Dit is C voorbeeld 2"); - } - - Deze listing kun je vervolgens compileren, assembleren en - linken met: - CF CVB2 - CG -K CVB2 - M80 = CVB2 /Z - L80 CVB2,MLVB2/S,CVB2/N/Y/E:MAIN@ - - CVB2.COM zal nu 58 bytes groot zijn. Indien je echter met de - oude library had gelinked (middels l80 - cvb2,mlvb1,cvb2/n/y/e:main@), dan was CVB2.COM echter 61 - bytes groot geweest omdat dan ook de overbodige bchget was - meegelinked. - - Om ook nog gebruik te kunnen maken van de functie parameter - checker (fpc), dient de source nog iets uitgebreid te - worden. Om FPC te gebruiken, moeten namelijk lege C body's - worden opgenomen zodat FPC weet hoeveel en wat voor type - parameters gebruikt worden door de functie. Aangezien de - source hiervoor echter door CF.COM en door M80.COM gehaald - moet kunnen worden, is er een klein probleem (de programma's - verwachten namelijk een compleet verschillende syntax). Door - nu echter van een truuk gebruik te maken, kunnen evengoed de - lege C routine body's en de echte ML routines in ��n enkele - source worden gebruikt. De truuk bestaat eruit dat ; voor - M80 betekent dat er commentaar begint (en dat alles wat er - achter staat dus niet van belang is), terwijl het voor CF - een scheidings teken tussen te statements is, dus CF negeert - een losse ;. - - De source kan dan beginnen met "; /*". Alles wat daarna op - dezelfde regel staat, is dan zowel voor M80 als voor CF - commentaar. Door hierna goed af te wisselenen met /* en */ - (voor CF) en .comment # en # voor M80, is het mogelijk om - alles in 1 source te houden. - - - E E N V O O R B E E L D L I B R A R Y - - De library XS-CLIB1.MAC is de volledig ontwikkelde versie - van de eerste voorbeelden. Er zitten ook nog een paar - functies bij om de VDP aan te sturen. De volledig afgewerkte - library staat tevens op de disk (XS-CLIB1.REL). Om er - gebruik van te maken, dient de parameter XS-CLIB1/S te - worden opgenomen achter L80 in in de batchfile waar je - normaal je C programma's mee linkt. Om de functies te - gebruiken, dien je ook nog de header file XS-CLIB1.H op te - nemen in je source. - - Met CF.COM kan uit deze source nu de .TCO file voor de - function parameter checker worden gehaald. De library zelf - kan worden aangemaakt met MX.COM. Het aanmaken van - XS-CLIB1.TCO en XS-CLIB1.REL gaat nu als volgt: - - - Zorg ervoor dat CF.COM, MX.COM, M80.COM, LIB80.COM en - AREL.BAT op de disk staan. - - Typ in: cf xs-clib1.mac om de .TCO file te maken. - - En typ vervolgens in: - MX -L XS-CLIB1 > TEMP.BAT TEMP - REN XS-LIB1.LIB XS-LIB1.REL - om XS-CLIB1.REL te maken. - - Het bestand XS-VB.C is een voorbeeld van het gebruik van - deze library. Dit bestand is te compileren met MK-XSVB.BAT. - - Alex Wulms diff --git a/sunrise_special/4/BDOS foutafhandeling.md b/sunrise_special/4/bdos_foutafhandeling.md similarity index 100% rename from sunrise_special/4/BDOS foutafhandeling.md rename to sunrise_special/4/bdos_foutafhandeling.md diff --git a/sunrise_special/4/Boot2com.md b/sunrise_special/4/boot2com.md similarity index 100% rename from sunrise_special/4/Boot2com.md rename to sunrise_special/4/boot2com.md diff --git a/sunrise_special/4/Circle.md b/sunrise_special/4/circle.md similarity index 100% rename from sunrise_special/4/Circle.md rename to sunrise_special/4/circle.md diff --git a/sunrise_special/4/Copdisk.md b/sunrise_special/4/copdisk.md similarity index 100% rename from sunrise_special/4/Copdisk.md rename to sunrise_special/4/copdisk.md diff --git a/sunrise_special/5/C Cursus deel 6.md b/sunrise_special/5/C Cursus deel 6.md deleted file mode 100644 index ffb0257..0000000 --- a/sunrise_special/5/C Cursus deel 6.md +++ /dev/null @@ -1,338 +0,0 @@ - C C U R S U S D E E L 6 - 1 - - - - 1 . I N L E I D I N G - - Dit deel is bedoeld als afsluiting van de cursus. Denk nu - niet dat iemand door slechts deze zes tekstfiles te lezen - een volleerde C programmeur zal zijn, maar het is een basis. - Op een tweetal zaken na (en die worden direkt hierna - besproken) is zo ongeveer de hele taal C de revue - gepasseerd. Maar kennis van de taal is niet voldoende om er - goede programma's in te kunnen schrijven, ervaring is ook - van belang, en we kunnen de kunst ook gedeeltelijk afkijken, - gewoon door bestaande C-sources te bestuderen. - - Maar aangenomen dat we een project van enige omvang in C - willen uitvoeren - ik mag er toch wel van uitgaan dat deze - files niet alleen gelezen worden omdat 't plot zo spannend - is? - hoe kunnen we dan zoiets het beste aanpakken? Dat komt - in hoofdstuk 3 ter sprake. - - De hoofdstukken 4 gaat over het debuggen van C-programma's, - en hoofdstuk 5 behandelt de ontwikkeling van een vrij groot - voorbeeldprogramma. Deze laatste twee hoofdstukken worden in - de volgende Sunrise Special gepubliceerd. - - - 2 . N O G T W E E S T A T E M E N T S - - Al enige tijd terug heeft iemand mij erop gewezen dat ik - (foei toch!) een tweetal statements ben vergeten te - bespreken. Dat klopt inderdaad, maar tot mijn verdediging - wil ik dan wel aanvoeren dat deze twee statements in - principe geen extra mogelijkheden aan ons repertoire - toevoegen. - - - 2 . 1 H E T F O R - S T A T E M E N T - - Iedere programmeertaal schijnt een for-statement te moeten - hebben, en C is daar geen uitzondering op. Maar in C is het - niet nodig hem te gebruiken als simpele teller, zoals zal - blijken. De syntax is als volgt: - - for (; ; ) - - Heel obscuur. Maar het wordt wel duidelijker als we het - equivalente while-statement laten zien: - - ; - while () { - - ; } - - Toch is er een klein verschil: een continue-statement brengt - ons bij , en niet naar het begin van de while lus. Een - break-statement daarentegen doet in beide gevallen precies - hetzelfde. - - De meest gebruikelijke manier om een for-statement te - gebruiken is als volgt: - - for (cntr = 0; cntr < 60; cntr++) printf("%d ", cntr); - - Hier wordt het statement inderdaad als simpel tellertje - gebruikt, en de getallen 0 t/m 59 worden op het scherm - gezet. (De variabele 'cntr' is trouwens na afloop 60, hou - daar rekening mee!) - - We hoeven overigens niet alledrie de uitdrukkingen in het - for-statement te gebruiken: we mogen ze eventueel zelfs - alledrie weglaten, maar als we de middelste weglaten - ontstaat een eindeloze lus, die we alleen met een 'break' - kunnen verlaten. Sommige programmeurs geven de voorkeur aan - een - - for(;;) - - boven een - - while(TRUE) - - als ze zo'n eindeloze lus willen, maar dat is een kwestie - van persoonlijke stijl en smaak. - - - 2 . 2 H E T S W I T C H S T A T E M E N T - - Hoewel de functie van een switch-statement in principe ook - door het gebruik van if-statements kan worden gesimuleerd, - is het toch erg nuttig, en dan met name omdat het programma - er een stuk overzichtelijker van kan worden. Het komt - ongeveer overeen met het CASE-statement in PASCAL of in - mindere mate met de ON..GOTO in BASIC. Helaas is de syntax - een beetje lastig, maar het went snel genoeg: - - switch() - - En de syntax van het switch-block: - - { - - ... - [default: ] } - - Voor lees: een willekeurig aantal (ook nul!) - statements. De ... geeft aan dat een switch-block uit een - willekeurig aantal case-labels en bijbehorende statements - kan bestaat. Het default-label is optioneel, zoals aan de - vierkante haken is te zien. - - Case-labels hebben de vorm: case : - - Ok, dat is dus een switch-statement, maar wat doet 't nu - precies? Wel, eigenlijk is het heel eenvoudig: vanaf de - 'switch' wordt gesprongen naar het statement volgend op het - case-label waarvan de overeen komt met de waarde - van . Indien zo'n label niet bestaat wordt er naar het - statement volgend op 'default:' gesprongen, en als dat niet - bestaat wordt geen enkel statement in het switch-block - uitgevoerd, en gaat het programma gewoon verder. Een - voorbeeldje, snel, voor de hersens overbelast raken: - - switch(getch()) { - case 'j': - case 'J': printf("U drukte op de 'J'\n"); - break; - - case 'n': - case 'N': printf("U drukte op de 'N'\n"); - break; - - default: printf("U heeft 't niet begrepen...\n"); } - - Met getch() halen we een karakter van het toetsenbord - binnen, en afhankelijk van welke dat is springen we naar een - van de case-labels. Is het een 'j' dan vervolgen we na 'case - 'j':', en vanaf daar vervolgt het programma zijn weg, en - komt dan de printf-functie tegen. De case-labels zijn - uiteraard geen statements, ze dienen slechts om een bepaalde - plek in het switch-block aan te geven. De breakstatements, - dat ons het switch-block doen verlaten, zijn dan ook - essentieel, anders zou er komen te staan: - - U drukte op de 'J' - U drukte op de 'N' - U heeft 't niet begrepen... - - Dat levert wel weer wat hoognodige inspiratie voor - Sinterklaasgedichten, de komende december, maar verder heb - je er niet veel aan. Dit is een belangrijk verschil met een - taal als PASCAL, waar in een CASE-statement slechts die - statements uitvoert die bij het betreffende label horen. C - is wat dat betreft - trouw aan z'n reputatie - moeilijker, - maar flexibeler, en daar hebben we in bovenstaand voorbeeld - gebruik van gemaakt om de invoer niet in hoofdletters te - hoeven omzetten. - - Misschien ten overvloede: we mogen natuurlijk ook switch- - statements maken met int's of unsigned's in de 'switch', en - de constanten in de case-labels mogen elke vorm hebben: alle - constanten worden intern geconverteerd naar hetzelfde type - als de uitdrukking in de 'switch'. - - - 3 . G R O T E R E P R O J E K T E N I N C - - Wie vol goede moed een programmaatje in C begint te - schrijven, en er vervolgens hier en daar wat functies bij- - maakt merkt al gauw tot zijn grote schrik dat de source - sneller groeit dan het financieringstekort op de Russische - [Nvdr. Eh... is het niet GOSsische?] begroting, en bovendien - al even ondoorzichtig wordt. Ai, daar zitten we nu met onze - goede voornemens: het is dan wel niet zo'n zooitje als het - gemiddelde BASIC-programma (eh, we hebben onze variabelen - tenminste wel fatsoenlijke namen gegeven, niet?) maar een - hoop van onze functies beginnen al een paar honderd regels - lang te worden, omdat we in die functies steeds weer nieuwe - taken hebben ondergebracht. En ondertussen doet de compiler - er twintig minuten over om het programma te compileren, en - we hebben onze B: drive al afgekoppeld omdat de compiler - anders te weinig geheugen heeft... - - Klinkt dat bekend in de oren? Nou ja, we trappen er alle- - maal wel eens in, het begint allemaal zo klein, zo simpel. - Misschien is het wel tijd om een paar gouden regels op - papier te zetten: - - - P R O G R A M M E E R M O D U L A I R ! - - Dit is het krachtigste hulpmiddel om grote projecten - overzichtelijk te houden. In tegenstelling tot bijv. PASCAL - mag het programma namelijk in verschillende, kleinere - sources gesplitst worden, die apart gecompileerd mogen - worden. Pas in de laatste stap wordt dan alles samengevoegd - door onze linker. - - Hiermee worden we op verschillende manieren geholpen. Zo - gaat het compileren van kleine sources natuurlijk veel - sneller dan grote, en de compiler zal veel minder snel - geheugenproblemen krijgen. Het dwingt ons bovendien de - functies in logische, bij elkaar behorende groepen te - verdelen. Hierdoor wordt de logica (of het gebrek eraan) van - het programma veel duidelijker zichtbaar. Als we erg veel - moeite hebben om een logische opdeling te maken zijn de - functies waarschijnlijk te groot, en hebben elk teveel - taken. - - - H O U H E T K L E I N - - Zijn onze functies te groot en meer dan 50 regels is in - feite al te groot, en ongeveer 25 regels (een scherm vol) is - waarschijnlijk beter dan moeten we bovenstaand principe - gebruiken om onze functies te vereenvoudigen. In feite - moeten we in een enkele zin kunnen zeggen wat een functie - precies doet, en die zin moeten we dan als commentaarregel - voor de functie zetten, zoals: - - /* Haal de default-configuratie uit DEFAULT.CNF */ - - - K I S S - - Een acroniem: Keep It Simple and Stupid. Je kan dit zien als - een uitbreiding van voorgaande regel, en waarschuwt ons het - allemaal niet te mooi te willen doen. Een simpele (en - eenvoudig te begrijpen) routine laat zich gemakkelijker - aanpassen als in de loop van het programmeren de eisen eraan - iets veranderen, en zal minder snel voor subtiele bugs - zorgen. Als het programma klaar is en werkt kunnen we altijd - nog hier en daar de zaak optimaliseren. (De ervaring leert - echter dat we tegen die tijd allang blij zijn dat 't af is!) - Performance-freaks wil ik hier graag wijzen op de 90%-10% - regel, een vuistregel die erop neerkomt dat een programma - 90% van de tijd doorbrengt in slechts 10% van de code. Enige - prestatieverbetering is alleen dan te verwachten als we die - 10% aanpakken. Voor 90% van het programma blijft dan gewoon - de KISS-regel van toepassing. - - - I N F O R M A T I O N - H I D I N G - - Een principe wat vooral de betrouwbaarheid van een programma - ten goede zal komen is "information hiding". Hiermee wordt - bedoeld dat we een taakverdeling kiezen waardoor (groepen) - functies zoveel mogelijk onafhankelijk van elkaar opereren. - Zo is een MODEM-functie natuurlijk het gemakkelijkst te - gebruiken als we er eenvoudig karakters naar kunnen - schrijven, of ervan kunnen ontvangen zonder dat we ons druk - hoeven maken hoe dat verder gebeurt. Het eerste wat we in - zo'n geval doen is de MODEM-functie van een buffer voorzien - voor inkomende en uitgaande data: hierdoor wordt deze - functie veel makkelijker in het gebruik, omdat we geen - rekening meer hoeven houden met de precieze tijd waarop een - karakter arriveert. We "verbergen" dus de exacte - ontvangsttijd (die is meestal toch onbelangrijk). - - Maar we kunnen buffers niet onbeperkt groot maken: helemaal - kunnen we dus de tijdfactor niet uitschakelen. We zouden - echter kunnen overwegen om de MODEM-functie automatisch een - XOFF te laten sturen als de buffer - zeg - tweederde vol is, - en een XON al hij weer voor maar eenderde vol is. In dat - geval hebben we dus de fysieke manier van communiceren - helemaal afgeschermd van de rest van het programma, die naar - believen de informatie kan krijgen en verwerken. - - Dit voorbeeld maakt duidelijk hoe we een taakverdeling - kunnen kiezen die maakt dat functies elkaar zoveel mogelijk - als een simpele "black-box" zien, die zich niet druk hoeven - te maken hoe de anderen precies werken. Maar natuurlijk - mogen we geen belangrijke informatie verbergen: bovenstaande - MODEM-functie zou geen genade kunnen vinden in de "ogen" van - een ZMODEM-protocolfunctie, omdat in protocollen de timing - wel degelijk van belang is. Maar in dat geval kunnen we wel - weer een andere taakverdeling vinden door bijv. de - MODEM-functie de data alvast per frame te laten ontvangen: - dan wordt de timing voor de rest van het protocol weer - minder kritisch! - - Bovenstaand voorbeeld is natuurlijk niet meer dan dat: een - voorbeeld, en probeer het onderliggende principe in ieder - geval daarvan los te zien. Het is in ieder geval goed - gebruik om het aantal parameters van een functie te beperken - tot de essentiele (bij voorkeur vier of minder) en zo min - mogelijk van systeemvariabelen gebruik te maken (tenzij die - binnen het programma vrij constant zijn, zoals bijv. de - screen-mode). - - - E N T O T S L O T - - Hou het N E T J E S E N O V E R Z I C H T E L I J K !! - - Een paar tips: laat de regels netjes inspringen binnen - lussen en if..else statements en wees consequent hierin. - Ikzelf vind het prettigst om twee spaties in te springen, - maar sommigen vinden vier, of zelfs meer, overzichtelijker. - Een kwestie van smaak. - - Indien er veel regels staan tussen het begin van een lus en - het eind ervan werkt het vaak verduidelijkend om in een - stukje commentaar aan te geven waar het einde van de lus is, - zo ongeveer: - - while (ptr != NULL && *ptr != '\0') { - - } /* while (ptr !=... */ - - Gebruik voldoende commentaar, maar overdrijf niet. Geef wel - altijd (kort) aan wat een functie geacht wordt te doen, en - geef bij belangrijke (voornamelijk globale) variabelen aan - waar ze voor staan als dit al niet uit de naam duidelijk - wordt. - - Probeer een systeem aan te leggen in de keuze van namen. De - namen 'tmp' of 'temp', of zij die ermee beginnen of eindigen - zijn bij mij altijd tijdelijke variabelen, en andere - veelgebruikte (delen van) namen zijn 'src' (source = bron), - 'dst' (destination = bestemming), 'count' of 'cnt' (aantal), - 'siz' of 'size' (grootte), 'ptr' (pointer), 'x' en 'y' - (coordinaten) en 'buf' (buffer). Combinaties zijn ook - mogelijk, bv. 'bufsize', waaruit direkt blijkt dat het hier - de grootte van een buffer betreft. - - Met '#define' gedefinieerde constanten horen altijd in - HOOFDLETTERS. Dit is algemeen gebruikelijk onder de - C-programmeurs, die het meestal toch maar zelden met elkaar - over iets eens zijn. - - En tot slot, als je echt een flink project aan de broek - hebt: maak je aantekeningen in een LOGBOEK (blocnote, oud - schrift, etc.) zodat het gemakkelijker wordt zelfs na lange - tijd nog eens op het project terug te komen. - - Robert Amesz diff --git a/sunrise_special/5/Fout vertaler.md b/sunrise_special/5/Fout vertaler.md deleted file mode 100644 index 8e2454b..0000000 --- a/sunrise_special/5/Fout vertaler.md +++ /dev/null @@ -1,26 +0,0 @@ - F O U T V E R T A L E R - - - This TSR is downloaded in BBS Roefsoft, and translates all - error messages of MSX-BASIC 2.1 and disk-BASIC 1.0 into - Dutch. The effect of this is rather funny! - - - F I L E N I E T G E V O N D E N - - This is, as was to be expected, the translation of "File not - found". Actually it should be "Bestand niet gevonden". But - it's comical enough without "bestand". It's also a bit weird - that the TSR is called "Error Translator", and not - "Fout Vertaler". - - I hope nobody really needs this TSR, for the one who does - need it, can't play a single decent MSX-game, and can't - understand any scroll-text - and he can't even read this - text, and so he wouldn't even know the program would exist! - - Kasper Souren - - - P.S. The file ET.TSR is the meant TSR and you can find it on - this disk. diff --git a/sunrise_special/5/Frequenty analyzer.md b/sunrise_special/5/Frequenty analyzer.md deleted file mode 100644 index b16ed04..0000000 --- a/sunrise_special/5/Frequenty analyzer.md +++ /dev/null @@ -1,20 +0,0 @@ - F R E Q U E N C Y A N A L Y Z E R - - - Met FRQANAL.BAS is het mogelijk om op je turbo R samples te - onderzoeken op frequenties. Eerst wordt een stukje - gesampled, en dat wordt dan onderzocht. Vervolgens kun je - met de muis kijken welke frequentie veel voorkomt. - - DTMF.BAS doet hetzelfde, maar kijkt alleen maar naar de - druktoetsfrequenties, en geeft daarna op welke toets het - geweest is. Het werkte goed met mijn telefoon, al moet je - natuurlijk wel de juiste kant van de hoorn bij de microfoon - houden. - - Zonder KUN-BASIC werkt FRQANAL.BAS niet, en DTMF.BAS slechts - zeer langzaam. FRQANAL gebruikt namelijk ook een stukje - machinecode. Dat is eventueel wel om te zetten, maar wie - heeft nou niet de beschikking over KUN-BASIC? - - Kasper Souren diff --git a/sunrise_special/5/Gestruktureerd programmeren.md b/sunrise_special/5/Gestruktureerd programmeren.md deleted file mode 100644 index 180e585..0000000 --- a/sunrise_special/5/Gestruktureerd programmeren.md +++ /dev/null @@ -1,264 +0,0 @@ - G E S T R U C T U R E E R D P R O G R A M M E R E N - - - Vanaf de volgende Special ga ik een aantal teksten schrijven - over gestructureerd programmeren in machinetaal. Veel - programmeurs, zowel beginners als gevorderden, programmeren - niet gestructureerd en denken dat zij daardoor sneller - programmeren en dat hun programma's sneller zijn. Hoewel - mijn artikelen juist voor die programmeurs zijn bedoeld, - zullen zij daarom vaak aan hun oude stijl vasthouden. - - Ik was daarom van plan om een uitgebreid verhaal te - schrijven waarom het beter is om gestructureerd te - programmeren. Ik heb echter (erg) weinig tijd momenteel, en - kwam daarom het idee om de tekst die Alex van der Wal ruim - twee jaar geleden schreef over dit onderwerp hier "af te - drukken". Ik hoop dat iedereen na het lezen van onderstaande - tekst "bekeerd" is! - - Vanaf de volgende Special kunt u van mij een serie artikelen - verwachten over gestructureerd programmeren volgens de - methode van stapsgewijze verfijning (oftewel top-down). Tot - dan! - - Stefan Boer - - - I N L E I D I N G - - Er zijn nogal wat mensen onder jullie die zichzelf - programmeur noemen, maar vaak blijkt dan dat ze dat heilige - woord misbruiken. Een programmeur is nl. iemand die een - probleem onder de loep neemt en die daarna via vaste regels - en instrukties tot een oplossing komt. Dat betekent dat zijn - programma aan een aantal standaard voorwaarden voldoet. - - De belangerijkste afspraak waar hij zich aan moet houden is - dat het programma dat hij geschreven heeft ook voor andere - programmeurs ontcijferbaar moet zijn zonder dat je dagen - bezig bent om alles te begrijpen. Het is echter helaas een - feit dat mensen die bezig zijn om de kunst van het - programmeren te leren deze afspraak negeren. Vaak loopt het - zo uit de hand dat deze mensen hun eigen programma's niet - eens meer snappen die ze twee weken eerder hebben - geschreven. (Ik spreek uit ervaring.) - - - S P A G H E T T I - - Denk nou niet meteen dat ik een arrogante zak ben omdat ik - kritiek op andermans programmeerknoeisels heb, want ik geef - van harte toe dat ik ook zo'n prutser ben geweest. Er is - echter eens een moment in mijn leven geweest dat iemand me - op het feit wees dat mijn programma's de vergelijking met - een hoop stront niet overleefden. Vanaf dat moment heb ik al - mijn aandacht gericht op het leren van de schone kunst van - het gestructureerd programmeren. - - Deze teksten die ik over dit inderwerp ga schrijven zijn - niet bedoeld als cursus, omdat dat helemaal geen effect zou - hebben. Dat zou nl. alleen maar betekenen dat ik jullie mijn - programmeerstijl zou opdringen en dat is niet de bedoeling. - Ze zijn meer bedoeld om jullie aan te sporen ook op zoek te - gaan naar een standaardisatie van jullie programma's. Het - enige dat ik kan doen is jullie een aantal tips geven over - wat voor standaardisatie geschikt is en hoe dat in de - praktijk werkt. [Noot van Stefan: die serie artikelen is er - nooit gekomen, daar ga ik dus verandering in brengen!] - - Er zullen ongetwijfeld mensen zijn die al een eigen methode - van werken hebben en die in staat zijn programma's te - schrijven die best voor andere mensen leesbaar zijn, maar ik - neem nu de stelling dat de methode die ik ga bespreken de - beste is. Dit omdat hogere programmeertalen ook allemaal uit - gaan van deze methode, dus als je deze methode al kent op - een moment dat je met een hogere taal geconfronteerd wordt - dan kan dat alleen maar voordeel opleveren. - - De methode van werken die ik (en met mij vele informatici) - gebruiken is niet een strakke methode en dat is maar goed - ook omdat je de denkwijze van mensen maar heel moeizaam kunt - be�nvloeden. Bovendien zou programmeren een hele saaie - bezigheid zijn als iedereen zich aan een absolute - programmeerstandaard hield. - - Goed, ik denk dat het tijd wordt om maar eens te beginnen en - ik hoop dat deze artikelen veel mensen die nu nog een - spaghetti programmeerstijl gebruiken (oftewel een - 'kbenblijdattutwerkt' stijl) zich tot het ware geloof zullen - bekeren. (Waar heb ik dat eerder gehoord?) - - - T O P - D O W N - - De methode die ik altijd gebruik heet de top-down methode en - is uit te leggen met een voorbeeld. Stel je zit in een - wolkenkrabber op de 100ste verdieping. Vanuit die hoge - positie kan je de hele stad overzien, maar nu ga je naar - beneden zodat je steeds minder van het geheel gaat zien, - terwijl de detaillering van het deel dat je nog wel kunt - zien steeds groter wordt. - - De stad in het voorbeeld is het op te lossen probleem. Je - kan het hele probleem van boven overzien, waarbij je alleen - de verschillende deelproblemen die je op moet lossen kunt - overzien. Als je lager komt kan je steeds beter de oplossing - van de verschillende deelproblemen zien die op hun beurt ook - weer uit deelproblemen kunnen bestaan. Op het moment dat de - lift beneden is zijn voor alle deelproblemen oplossingen - gevonden, oftewel het programma is af. Natuurlijk is het - handig af en toe even met de lift omhoog te gaan zodat je - weer helemaal precies weet waar je mee bezig bent. Ook is - het handig om even naar de verschillende deelproblemen kijkt - voordat je met programmeren begint om er achter te komen of - je alle problemen wel op kan lossen. Lukt dit nl. niet dan - ben je dus niet in staat om het programma te schrijven en is - het raadzaam om eerst wat minder hooi op je vork te nemen. - - - D E P R A K T I J K - - Goed, we zullen nu eerst de puur theoretische oplosmethode - bekijken voor machinetaal. - - Bij de top-down methode is het heel handig om modulair te - programmeren. Dat betekent dat je deelproblemen apart oplost - zodat ze in principe ook los van de rest van het programma - werken en dat je ze in andere programma's in kunt bouwen. - Het beste voorbeeld van een modulair geschreven routine is - de BIOS. Deze routines zijn zo standaard dat ze door alle - verschillende programma's gebruikt kunnen worden. Een andere - eigenschap van een modulaire routine is dat informatie die - de ene routine maakt ook door andere routines bruikbaar is. - De BIOS voldoet ook aan deze eis, zo wordt b.v. het huidige - schermnummer op een vaste plaats bewaard. Het blijkt dat het - standaardiseren van eigen routines een zeer taaie klus is en - het is voor de meeste eigen geschreven routines vaak niet - echt belangerijk. De eigenschap dat eigen routines ook los - van de rest van programma kunnen werken en uitwisselbaar - zijn is veel belangerijker. - - Goed, een programmeur is dus blijkbaar iemand die volgens - een vaste methode (in ons geval de top-down methode) en - volgens het principe van modulair programmeren programma's - schrijft. - - Als er mensen onder jullie zijn die later programmeur willen - worden dan kan ik ze aanraden om de bovenstaande alinea goed - te onthouden want deze regel geldt in de praktijk voor alle - programmeertalen die ooit ontworpen zijn sinds de invoering - van de CPU. - - Programma's die volgens de top-down methode zijn geschreven - zijn heel eenvoudig herkenbaar. Ze beginnen nl. vaak met een - lijstje EQU instrukties waarna een hoofdprogramma volgt - waarin de instruktie CALL overheerst. Achter dat - hoofdprogramma staan altijd de routines waar die CALL's - heenspringen en achter deze routines staan dan vaak nog een - lading data's. - - De routines waar de CALLs heenspringen zijn altijd modulair, - maar dat betekent in de praktijk vaak dat ze niet in andere - programma's bruikbaar zijn omdat ze te specifiek bij het - programma horen waar ze voor geschreven zijn. Een voorbeeld - hiervan is b.v. een routine bij een lichtkrant (scroller) - die de plaats van het volgende stukje letter berekend en - zoekt, terwijl een routine die een lijn trekt heel goed - uitwisselbaar is. - - Als je mij gelooft dan moet je nu dus ook geloven dat een - programma dat met de top-down methode geschreven is ook door - andere programmeurs ontcijferd kan worden. Dit is wel waar, - maar het komt niet door de top-down methode want die stelt - eigenlijk niets voor. Nee, het komt door een bijzonder - aangenaam bijverschijnsel dat altijd optreedt als je de - top-down methode gebruikt. Want het programmeren in - spaghetti stijl wordt nl. onmogelijk gemaakt. - - - I T A L I A A N S E K O O K K U N S T - - De spaghetti stijl is de stijl waar de meeste prutsers mee - beginnen. Er wordt konstant heen en weer gesprongen tussen - verschillende routines waardoor het programma wordt - gedegradeerd tot doolhof voor iemand die de werking ervan - moet uitvissen. Bovendien slaan dit soort programma's nogal - snel (en heel heel vaak) vast als er kleine (of grote) - veranderingen in worden aangebracht. Je begrijpt dat het - vinden van bugs een zeer slopende en tijdrovende bezigheid - is (gniffel gniffel). Het enige voordeel dat deze misbaksels - hebben is dat ze inderdaad redelijk kraakvrij zijn, maar - helaas geldt dat ook vaak voor de programmeur. (Ik spreek - trouwens nog steeds uit ervaring.) - - De spaghetti stijl wordt onmogelijk gemaakt omdat je heel - goed op je stack moet letten omdat een routine die met een - CALL wordt aangeroepen met een RET weer terug moet, terwijl - de stack er bij het ingaan van de routine hetzelfde uit moet - zien als bij het terug gaan om hele vreemde errors te - voorkomen. Het is natuurlijk altijd mogelijk om spaghetti te - maken, maar de top-down methode heeft een sterk remmende - werking op deze gang van zaken. - - - Je moet dus een aantal regels gebruiken: - - - Je mag nooit van de ene routine in de andere routine - springen. Wel mag je in de eigen routine naar hartelust de - meest vreemde bokkensprongen maken. Moet je in een routine - een andere aanroepen, dan moet dit met een CALL statement - gebeuren. - - - Als je in een routine iets op de stack zet, dan moet dit - in dezelfde routine weer van de stack gehaald worden. Dus - niet alleen PUSH en POP, maar ook CALL of iets anders. - (Deze regel kan in een hogere programmeertaal niet eens - ontdoken worden.) - - Er blijken uitzonderingen mogelijk op deze regels, maar een - goede programmeur laat zich daar niet door uit het veld - slaan en bedenkt een manier zodat deze regels toch - gehandhaafd blijven. - - - V O O R D E L E N - - - Programma's zijn goed leesbaar en begrijpbaar - - Programma's zijn snel bugvrij te maken en te houden. - - Hoe langer je oefent, des te sneller je in staat zult zijn - om een foutloos programma te schrijven. - - Je maakt een fantastische opstap om aan een hogere - programmeertaal te beginnen. (Overigens is BASIC geen - hogere programmeertaal.) - - Je mag jezelf programmeur noemen - - Je kunt eens lachend op prutsers neerkijken (even - vergetende dat je er zelf ook een bent geweest). - - - N A D E L E N - - - Het is lastig om je alles aan te wennen. - - Tja, eh... Er zijn eigenlijk geen nadelen van belang. - - Goed, dat was het voorlopig. Ik zal zeer zeker een volgende - keer een meer praktische benadering van deze methode geven. - - A A N A L L E P R U T S E R S - - Lig over deze tekst maar eens een nachtje wakker en maak een - besluit of je in de toekomst door wilt gaan met je gepruts, - of dat je bereid bent om iets anders te proberen. - - - Hopelijk heb ik niet al te veel mensen op hun (meestal - uitschuifbare) tenen getrapt, maar ik kan deze mensen - verzekeren dat ze vanzelf zullen struikelen als ze blijven - zweren bij de Italiaanse kookkunst (spaghetti). - - Alex van der Wal - - - (Nu al 1.5 jaar geen prutser meer, alhoewel ik dit jaar het - meeste geleerd heb.) [Nvdr. Klopt niet, omdat deze tekst al - 2 jaar oud is.] diff --git a/sunrise_special/5/HD op write protected.md b/sunrise_special/5/HD op write protected.md deleted file mode 100644 index 45c83e8..0000000 --- a/sunrise_special/5/HD op write protected.md +++ /dev/null @@ -1,21 +0,0 @@ - H D O P W R I T E P R O T E C T E D - - - Soms is het fijn om je HD op write protected te hebben - staan. Bijvoorbeeld bij het proberen van een of ander - luguber diskje met je harddisk aangesloten. Het op write - protected zetten is op zich niet veel moeite. Alleen even - FORMAT onder MSX-DOS of CALL FORMAT onder BASIC en een paar - instellingen. - - Maar het is lastig als je dat 4 keer in moet typen (voor - elke partitie ��n keer). Een batchfile lijkt de oplossing, - maar dan wordt het vrij traag. Zo kwam Erik Maas al een hele - tijd geleden op het idee om PROTECT.COM te maken. Een - COM-file die even snel de harddisk op write protected zet. - - De source PROTECT.GEN staat ook op disk, zodat je het simpel - kunt aanpassen voor een harddisk met een ander aantal - partities. - - Kasper Souren diff --git a/sunrise_special/5/IO Interface.md b/sunrise_special/5/IO Interface.md deleted file mode 100644 index 9ec8d6b..0000000 --- a/sunrise_special/5/IO Interface.md +++ /dev/null @@ -1,292 +0,0 @@ - I / O I N T E R F A C E - - - - J O Y S T I C K E N T O E T S E N B O R D - - Over het gebruik van joysticks en mouse via I/O poorten is - nog niet veel gepubliceerd, waardoor (nog) vaak gebruik - wordt gemaakt van de "trage" MSX ROM BIOS. Door gebruik te - maken van de I/O poorten kan het uitlezen en vooral het - verwerken van de informatie veel sneller geschieden (tja, - bedenk eens een leuk woord?). - - - P S G P O O R T E N - - Zoals mischien bekend is, wordt de PSG niet alleen gebruikt - voor het generen van geluiden maar ook voor het uitlezen van - informatie voor de joysticks, mouse, trackball, en leespen. - Deze PSG gebruikt twee 8-bit I/O poorten, poort A en B - respectievelijk r#14 en r#15. - - De PSG gebruikt de volgende I/O poorten: - - - &HA0 register poort. Geef hierin op het register dat moet - worden gelezen, of beschreven. - - &HA1 schrijf poort. Hier kan de data in worden geschreven - die naar het register - opgegeven in &HA0 - moet. - - &HA2 lees poort. Na het opgeven van welk register er moet - worden gelezen, zal hier de data in staan. - - - Een overzicht van de (joystick) poorten: - - interface 1 interface 2 - +-------------------+ +-------------------+ - | 1 2 3 4 5 | | 1 2 3 4 5 | - | 6 7 8 9 | | 6 7 8 9 | - +-------------------+ +-------------------+ - - (8) - naar poort B:b4 (8) - naar poort B:b5 - (5) - +5V (5) - +5V - (9) - nul (9) - nul - - De terminals (pennen) 1,2,3,4,5 en 6 van beide poorten - worden samen gevoegd en worden gezonden naar poort A:b0-b5. - - - F U N C T I E V A N D E P O O R T E N - - De twee poorten worden als volgt gebruikt: - - Poort A b7 b6 b5 b4 b3 b2 b1 b0 - r#14 cas x trB trA DR3 DR2 DR1 DR0 - - cas: data input van cassette. - trA: Vuurknop A - trB: Vuurknop B - DRx: Joystick richting. - DR0 = omhoog - DR1 = omlaag - DR2 = links - DR3 = rechts - - Noot: De bits zijn ge�nverteerd, dus 0=aan en 1=uit. - - - Poort B b7 b6 b5 b4 b3 b2 b1 b0 - r#15 ar In 2t8 1t8 0 0 0 0 - - ar: Arabische led. (0=ON) - in: Interface nr. (0=interface 1) - 1t8: Verbonden met pen 8 van interface 1, voor de mouse. - 2t8: Verbonden met pen 8 van interface 2, voor de mouse. - - Noot: Ook hier zijn de bits ge�nverteerd. - - - L E Z E N V A N E E N J O Y S T I C K - - Om joystick 1 te lezen, zullen we eerst b6 van r#15 nul - moeten maken. Let hierbij op dat de andere bits niet worden - verwaarloosd. Na het schrijven van r#15, kan de joystick - status worden uitgelezen. Laat ik dit verduidelijken met een - voorbeeld: - - ; Read Joystick. - ; In: C, joystick nr.(&H00=stick #1, &H40=stick #2) - ; Out: A, joystick status - RD_JOY: DI - LD A,15 - OUT (&HA0),A - IN A,(&HA2) - AND &B10001111 ; interface 1 - OR C - OUT (&HA1),A - LD A,14 - OUT (&HA0),A - IN A,(&HA2) - EI - RET - - Als eerste wordt r#15 gelezen, omdat somige bits moeten - worden bewaard. Door de AND functie zal b6 nul worden, - waardoor interface 1 zal worden gebruikt. Register 'C' is - nul, dus zal b6 ook niet worden gezet (als je joystick 2 wil - lezen, moet b6 van 'C' gezet worden). Hier na wordt de - waarde weer naar de PSG geschreven. Door nu r#14 te lezen, - zal het A register de joystick1 waarden bevatten. - - - P R A K T I S C H G E B R U I K - - Om nu bijvoorbeel in een spel de stick waarde te lezen, kan - er gebruik worden gemaakt van de ROM-BIOS "GTSTCK" (&HD5). - Deze routine doet feitelijk het volgende: - - Kijkt welke stick er moet worden gelezen (opgegeven in 'A' - register). Dat kan zijn: 0, Keyboard 1, Joystick #1 2, - Joystick #2. Stel we willen de waarde van Joystick #1 weten. - De BIOS routine leest eerst de stick waarde uit de PSG - poorten. Vervolgens zal uit een tabel de stickwaarde worden - gelezen. Deze waarden zijn hopelijk wel bekend (1=omhoog, - 2=omhoog/rechts, 3=rechts etc.). Afhankelijk van deze waarde - die wordt terug gegeven, kan in een eigen applicatie naar - een bepaald adres worden gesprongen. Maar zou het niet veel - sneller zijn als we inplaats van de stickwaarde, een Jump - adres terug zouden krijgen. Hierdoor hoeven we niet eerst de - stick waarde te onderzoeken, om daarna naar een label te - springen. - - Als we even verder borduren over zo'n routine zou het ook - wel makelijk kunnen zijn om, in plaats van de stick nummer - op te geven, gewoon alle sticks uit te laten lezen. Met als - prioriteiten: Keyboard, Joystick #1, Joystick #2. - - Als we nu ook nog een tabel pointer adres opgeven, waaruit - de adressen kunnen worden gelezen, dan zouden we een pracht - van een routine hebben. Deze zou niet alleen snel zijn, maar - ook zeer multifunctioneel. Immers we hoeven alleen maar een - tabel adres op te geven, waar in staat waar naar toe moet - worden gesprongen als de corresponderende stick waarde wordt - gelezen. Zo'n routine zal er dan als volgt uit komen te - zien: - - ; Read Stick(s) - ; In: HL= Tabel pointer adres. - ; Out: HL= Jump adres. (0=invallid) - RDSTCK: CALL RDS_KB ; Lees keyboard. - AND &H0F - CP 15 ; KB=0 ? - LD C,0 - CALL Z,RD_JOY ; Ja, dan lees joystick #1 - AND &H0F - CP 15 ; Is deze ook nul ? - LD C,&H40 - CALL Z,RD_JOY ; Lees dan joystick #2 - AND &H0F - LD C,A - LD B,0 - ADD HL,BC - ADD HL,BC - PUSH DE - LD E,(HL) ; adr Laag - INC HL - LD D,(HL) ; adr Hoog - EX DE,HL ; HL=adres - POP DE - RET - ; Read Keyboard cursors. (same as RD_JOY, but now KB) - RDS_KB LD A,8 - CALL RDKMAT ; [RDKMAT] = BIOS &H0141 - RRCA ;>Zorg er voor dat de bits - RRCA ; overeen komen met die van - RRCA ; de joysticks: deel door 8, - SET 3,A ; swap bits 2,3 (L -> R -> L) - BIT 2,A - JP NZ,RSKB.0 - RES 3,A - RSKB.0 SET 2,A - BIT 7,A - RET NZ - RES 2,A - RET - - Bij het lezen van de Cursors wordt rij 8 van het toetsenbord - matrix gelezen, en geconverteerd zodat de bits van de - cursors en joystick het zelfde zijn. De cursors bits hebben - namelijk deze volgorde: (rij 8) - - b7 b6 b5 b4 b3 b2 b1 b0 - r8 RGT DWN UP LFT x x x x - - RGT: Rechts - DWN: Omlaag - UP: Omhoog - LFT: Links - - Ook hier zijn de bits weer omgedraaid, dus 0=AAN en 1=UIT! - - Vergelijk de bits maar een met die van de joystick. Na het - converteren zal de cursor waarde het zelfde zijn als die van - en joystick, zodat we maar een pointer tabel hoeven aan te - maken. De bit-waarden van alle sticks: - - b0: Omhoog - b1: Omlaag - b2: Links - b3: Rechts - - Als een stick-waarde gelijk ik aan 15 (wat dus nul is als de - bits zijn geinverteerd), dan zal een volgende stick worden - gelezen. De pointer tabel zal er als volgt uit moeten zien: - (bevat 16 adressen) - - STCKTB: DB 0, 0, 0, 0, R/D, R/U, R, 0 - DB L/D, L/U, L, 0, L, 0, D, U - - L: Links - R: Rechts - D: Omlaag - U: Omhoog - en combinaties: U/L= Omhoog en Links. - - De waarde die uit de RDSTCK routine komt, is nu een adres. - Als we in onze eigen applicatie een jump routine aanroepen - met het adres in HL, dan zal deze de betreffende routine - aanroepen indien het adres ongelijk is aan nul. Een - voorbeeld van een dergelijke jump-routine: - - JUMPER: LD A,H - OR L - RET Z ; HL=0 - JP (HL) ; Spring naar een adres. De return - ; in die routine keert terug naar - ; waar JUMPER is aangeroepen. - - Met deze routine moet het nu mogelijk wezen om snel (save) - en simpel gebruik te kunnen maken van de cursors en beide - joysticks. - - Nu resten alleen nog de vuurknoppen. Als we net zo'n soort - routine maken als RDSTCK, waarbij ALLE vuurknoppen worden - gelezen (natuurlijk onderscheid makend tussen vuurknoppen A - en B). Als we voor vuurknop 1 de spatiebalk, joystick 1 knop - A en joystick 2 knop A nemen, zal de routine er als volgt - uit komen te zien: - - ; Read Trigger #1 - ; Out: Zerro flag, 0=ON, 1=OFF - RDTRG1: LD A,8 ; Lees spatie - CALL RDKMAT - AND &H01 ; spatie ingedrukt? (bit 0) - RET Z ; Ja! - - LD C,0 ; Joystick #1 - CALL RD_JOY - AND &H10 ; Vuurknop A (bit 4) - RET Z ; Ja! - - LD C,&H40 ; Joystick #2 - CALL RD_JOY - AND &H10 ; Vuurknop A - RET - - Voor vuurknoppen B, kunnen we wat betreft het keyboard de - GRAPH toets gebruiken: - - ; Read Trigger #2 - ; Out: Zerro flag, 0=ON, 1=OFF - RDTRG2: LD A,6 ; Lees GRAPH - CALL RDKMAT - AND &H40 ; ingedrukt? (bit 2) - RET Z ; Ja! - LD C,0 ; Joystick #1 - CALL RD_JOY - AND &H20 ; Vuurknop B (bit 5) - RET Z ; Ja! - LD C,&H40 ; Joystick #2 - CALL RD_JOY - AND &H20 ; Vuurknop B - RET - - De routine is bijna het zelfde als RDTRG1. Het enige - verschil is dat hier de B vuurknop wordt gelezen. - - Het extra voordeel van al deze routines is dat er nu niet - van het ROM-BIOS gebruikt wordt gemaakt. Met deze informatie - moet het mogelijk zijn om de joystick en cursors voledig te - kunnen gebruiken. - - R�man van der Meulen diff --git a/sunrise_special/5/Interrupt mode 2.md b/sunrise_special/5/Interrupt mode 2.md deleted file mode 100644 index 470e972..0000000 --- a/sunrise_special/5/Interrupt mode 2.md +++ /dev/null @@ -1,139 +0,0 @@ - I N T E R R U P T M O D E 2 - - - De Z80 kent 3 interrupt modes. Het hele operating system van - MSX werkt maar met ��n van deze modes, te weten IM 1 - (Interrupt Mode). Feitelijk is dit een beperking omdat de - andere interrupt modes zeer interessante mogelijkheden - bieden. - - De precieze werking van de verschillende interrupt modes is - nader beschreven in een eerder artikel op Sunrise Special. - Interrupt mode 0 is op MSX niet bruikbaar, IM 1 wordt - normaliter gebruikt en IM 2 is een twijfelgeval. - - In het eerdere artikel heb ik beweerd dat ook IM 2 op MSX - niet bruikbaar is, maar dat is niet helemaal waar. Om het - geheugen eerst wat op te frissen volgt eerst even een korte - uitleg van IM 2. - - - I M 2 - - IM 2 is op Z80 de zgn. 'Vector Interrupt' mode. Dat houdt in - dat er naar verschillende ISR's (Interrupt Service Routine) - gesprongen kan worden na het optreden van een interrupt. Op - Z80 werkt dit als volgt. - - In het geheugen staat een tabel van max. 256 bytes waar - praktisch per twee bytes een 16 bits adres kan staan. Totaal - zijn volgens deze rekening 128 adressen mogelijk. In het I - register van de processor moet nu het HI byte van het - startadres van deze tabel komen. - - &HC000 = vector entry 0 - &HC002 = vector entry 1 - ... - &HC0FE = vector entry 127 - - Het I register moet hier de waarde &HC0 hebben waardoor de - processor het startadres van de tabel weet. - - IM 2 gaat er van uit dat het interrupt genererende apparaat - niet alleen het INT lijntje aktief maakt, maar dat ditzelfde - apparaat (bv. de VDP) ook een getal op de bus zet. In ons - voorbeeld mogen dat dan alleen positieve getallen zijn. Stel - een chip genereert een interrupt en zet de waarde 2 op de - bus. De processor gaat nu de waarde van het I register - combineren met de waarde die op de bus komt tijdens een - interrupt. Daaruit volgt dan een 16 bits waarde (&HC002 in - dit voorbeeld). De processor leest nu het 16 bits getal - vanaf dit gecombineerde adres en springt vervolgens naar het - zojuist gelezen adres. - - Vb: - - &HC000 = (&H8000 = ISR 1) - &HC002 = (&H9000 = ISR 2) - I = &HC0 - Indien chip A een interrupt genereert en de waarde 0 op de - bus zet zal uiteindelijk naar adres &H8000 gesprongen - worden. Indien chip B de waarde 2 op de bus zet zal - uiteindelijk naar adres &H9000 toegesprongen worden. Indien - chip C de waarde 1 op de bus zou zetten zal naar adres &H80 - gesprongen worden (voer voor de pro's). - - Het voordeel van deze methode is dat er geen vertragende - routines meer nodig zijn om er achter te komen van welke - chip de interrupt af komt. Dat wordt allemaal door - hardware geregeld. Het enige waarvoor gezorgd moet worden is - dat indien er verschillende chips zijn die interrupts - genereren deze allen een verschillende waarde op de bus - zetten. - - - I M 2 E N M S X - - IM 2 is op MSX niet expliciet nodig omdat er maar 1 chip is - die een interrupt aan de processor door kan geven, nl. de - VDP. Daar komt nog bij dat de VDP helemaal geen waarde op de - bus zet als deze een interrupt genereert, dus IM 2 lijkt op - MSX nutteloos. - - Vanuit die gedachtengang heb ik destijds beweerd dat IM 2 op - MSX niet mogelijk is, wat niet helemaal waar blijkt te zijn. - Het is op MSX mogelijk om 1 vectorinterrupt te gebruiken - i.p.v. de praktische 128 in het vorige voorbeeld. Op MSX is - de Z80 zelf de enige chip in de computer die een lees of - schrijfaktie op de bus kan beginnen. De CPU is dus de enige - 'Bus Master'. Indien zelfs de Z80 niet op de bus schrijft - zal de waarde op de bus altijd &HFF zijn. De buslijnen zijn - van het 'Pull up' type (open collector uitgang voor de - electrotechneuten) wat dus praktisch neerkomt op de waarde - &HFF. - - Treedt er nu een interrupt op (altijd afkomstig van de VDP) - dan zal de Z80 indien IM 2 aktief is op de bus kijken en de - waarde &HFF zien. Indien het I register de waarde &HC0 heeft - zal dus de 16 bits waarde vanaf adres &HC0FF gelezen worden - waarna naar deze waarde gesprongen wordt. - - Het praktisch nut van dit 'geintje' is dat zo voorkomen kan - worden dat naar adres &H38 gesprongen wordt. We kenden al - een geintje om via &HFD9A te voorkomen dat de hele rimram - die normaal gesproken bij een interrupt uitgevoerd wordt - over te slaan. Een andere methode was het uitschakelen van - de ROM-BIOS waardoor een eigen routine vanaf adres &H38 - gezet kan worden. - - Het uitschakelen van de ROM-BIOS is echter vrij lastig - (vooral in combinatie met de BDOS). Via IM 2 is het nu - echter mogelijk om te voorkomen dat er naar adres &H38 - gesprongen wordt. Daarmee is het dus mogelijk om wel een - kompleet eigen ISR te schrijven, terwijl de ROM-BIOS gewoon - 'aan' kan blijven staan. - - Het is overigens zeer eenvoudig om een klein - testprogrammatje te maken dat met IM 2 werkt. Dat kan er bv. - zo uit zien: - - ORG &HC000 - - RUN: DI - LD HL,&H38 - LD (&HC0FF),HL - LD A,&HC0 - LD I,A - IM 2 - EI - RET - - De werking van dit programma laat zich raden. - - Het is best leuk om eens te stoeien met IM 2. Overigens zijn - de termen IM 0, IM 1 en IM 2 ook assembler instrukties die - als zodanig letterlijk gebruikt kunnen worden. Let wel even - op dat je na afhandeling van een ISR de interrupts weer aan - zet. - - Alex van der Wal diff --git a/sunrise_special/5/MIDI een taal in beweging.md b/sunrise_special/5/MIDI een taal in beweging.md deleted file mode 100644 index 50c3160..0000000 --- a/sunrise_special/5/MIDI een taal in beweging.md +++ /dev/null @@ -1,463 +0,0 @@ - M I D I : E E N T A A L I N B E W E G I N G - - - MSX is in de ban van MIDI. Alweer heel wat programma's zijn - intussen op de markt verschenen, welke gebruik maken van die - rare ronde aansluitingen, die zoveel lijken op de aloude - audio-aansluitingen. Maar wat is MIDI nu eigenlijk? Dat deze - vraag niet zo gemakkelijk te beantwoorden is als ze op het - eerste gezicht lijkt, wil ik in dit verhaal duidelijk maken. - - MIDI is namelijk heel wat meer dan een methode om data te - sturen naar een keyboard, module of synthesizer. Hoevelen - van u wisten bijvoorbeeld dat MIDI ook bedoeld is om special - effects zoals vuurwerk en rookmachines e.d. aan te sturen? - Om dat allemaal te kunnen is MIDI in eerste instantie - weliswaar niet ontwikkeld, maar is ze wel uitgegroeid. MIDI - is een volwaardige taal geworden. Compleet met grammatica en - vocabulaire. Zelfs compleet met de bij elke taal horende - uitzonderingen op de regels. - - En zoals bij elke taal is het ook bij MIDI noodzakelijk om - de grammatica te leren vooraleer men de taal kan spreken. - Gebeurt dit niet en ga je proberen de taal te spreken - voordat je de grammatica kent, dan zal je instrument je wel - VERSTAAN maar BEGRIJPEN is een andere zaak. Misschien - herinneren enkelen van u nog het lachwekkende Duits van de - Belgische keeper Jean-Marie Pfaff, toen-ie in Duitsland bij - een Duitse ploeg voetbalde. Dat ging zoiets als volgt: - - "Ja, die penalty. Ich zag al an sein anlaufen, dattie der - bal rechts van mij wollte gaan schiessen, dus war het f�r - mich auch nicht zo moeilijk die bal te stopfen..." - - Dat dit geen Duits is ziet elke Nederlander. Maar dat toch - zo ongeveer elke Duitser begreep wat Jean-Marie wilde zeggen - ligt toch minder voor de hand. Voor MIDI geldt ongeveer - hetzelfde. Zolang de foutjes tegen de grammatica nog niet t� - erg zijn, zal elk instrument begrijpen wat u bedoelt, maar - wilt u een echt 'gesprek' met uw instrument aangaan, dan - zult u toch de grammatica (en de vocabulaire van uw - instrument) enigszins onder de knie moeten hebben. Bovendien - is de vocabulaire niet bij elk instrument gelijk! Evenals - niet elk persoon het woord 'ambivalentie' kent [Nvdr. Eh?], - terwijl het toch een goed Nederlands woord is, zo kent ook - niet ieder instrument alle MIDI-codes. Kijk dus niet al te - gek op, wanneer uw instrument niet begrijpt wat u zegt, - terwijl u uzelf netjes aan de MIDI-regels houdt... - - - M I D I A L S T A A L - - Tot zover de (lange) inleiding. Want als we het hebben over - de grammatica van MIDI, dan hoort daar ook een uitleg bij, - nietwaar? Want, hoe 'spreek' je nu foutloos MIDI? - - Ten eerste bestaat MIDI alleen maar uit getallen. En wel de - getallen 0 t/m 255. De hele MIDI-vocabulaire bestaat dus uit - precies 256 'woorden'. - - Ten tweede dien je een juiste zinsopbouw te volgen. Net - zoals bij een echte taal. Laten we eens het volgende - Nederlandse zinnetje bekijken: - - Ik ga fietsen - - De woorden "ga" en "fietsen" zeggen iets over de "ik". Ze - verschaffen als het ware data bij het woordje "ik". Zonder - die data betekent het zinnetje niets. Dit geldt voor MIDI in - exact dezelfde mate. Elke MIDI-zin dient te beginnen met die - informatie, waarover je iets wilt zeggen. In MIDI-termen: - Elke zin dient te beginnen met een status-byte gevolgd door - een aantal databytes. Maar hoe herken je nu een statusbyte? - Dat hebben de heren MIDI-uitvinders iets intelligenter - gedaan dan de heren Nederlandse-taal-uitvinders. In de - Nederlandse taal is alleen door ervaring of studeren te - leren welke woorden nu statuswoorden zijn. In MIDI hebben ze - het simpeler gemaakt: Elk getal dat groter is dan 127 is een - statusbyte. Is het getal dus 127 of kleiner, dan betreft het - een databyte. - - Elke MIDI-zin dient dus te beginnen met een getal dat groter - is dan 127. Deze statusbytes vertellen het instrument wat - het moet gaan doen. De databytes daarna vertellen HOE het te - doen. - - De statusbytes zijn bovendien nog ingedeeld in 8 groepjes - van 16 getallen, corresponderend met het aantal MIDI-kanalen - dat MIDI kan aansturen. Dit is eenvoudiger zichtbaar te - maken wanneer de getallen hexadecimaal worden weergegeven: - Een statusbyte begint dan namelijk met een getal tussen 8 en - F en eindigt met een getal tussen 0 en F. Dit laatste getal - geeft het MIDI-kanaal aan (0=kanaal 1 t/m F=kanaal 16). - - Het eerste getal vertelt MIDI wat te gaan doen en welke - databytes te verwachten. Net als in een gewone taal: Na een - woordje 'je' verwacht je een werkwoordsvorm behorend bij - 'je', ook al zou deze werkwoordsvorm er hetzelfde uitzien - als een andere werkwoordsvorm. Bij een zinnetje als 'Je gaat - fietsen' is het tweede woord exact gelijk aan het tweede - woord uit de zin 'Hij gaat fietsen', terwijl de betekenis - (puur grammaticaal gezien) niet gelijk is. De eerste keer is - het een werkwoordsvorm behorend bij 'je', de tweede keer een - werkwoordsvorm behorend bij 'hij'. Maak van beide woordjes - 'gaat' maar eens een verbuiging van het werkwoord 'zijn'. - Het eerste 'gaat' wordt 'bent' het tweede 'gaat' 'is'. Voor - MIDI geldt dit ook. De databytes zijn voor alle statusbytes - gelijk van vorm (nl. 0 t/m 127) maar verschillen in - betekenis afhankelijk van het (hexadecimale) getal waarmee - een statusbyte begint. - - - N O T E O F F - - Als een statusbyte begint met een 8h (dit zijn dus de - statusbytes 80h t/m 8Fh) betekent dit voor MIDI dat er een - toon UITgezet moet worden. Er behoren nu twee databytes te - volgen, die aangeven welke noot uitgezet dient te worden en - hoe snel de toon moet uitsterven. Deze tweede databyte wordt - bij lange na niet door alle instrumenten begrepen, maar - weglaten is NIET toegestaan. Evenmin als de zin 'Ik voel mij - ambivalent' duidelijk wordt als het woord 'ambivalent' wordt - weggelaten, is het voor MIDI duidelijk wanneer de tweede - databyte wordt weggelaten. Het grote verschil is dat MIDI - handelt naar wat er WEL begrepen wordt en dus de toon uitzet - met een gemiddelde snelheid (terwijl misschien bedoeld was - om de toon extra snel uit te zetten). - - - N O T E O N - - De statusbytes beginnend met een 9h (dus 90h t/m 9Fh) laten - een toon AANzetten. Wederom worden er door MIDI twee - databytes verlangd, waarbij de eerste aangeeft welke noot - aan te zetten en de tweede de velocity (i.e. de hardheid - waarmee de toon aangeslagen dient te worden). Dit statusbyte - behoort tot de standaard-vocabulaire van elk instrument; - ieder instrument begrijpt het. - - Er geldt ook nog een uitzondering bij deze statusbyte, die - eigenlijk meer regel dan uitzondering is. Wanneer een noot - aangezet wordt met een velocity (dus tweede databyte) van 0, - wat dus feitelijk betekent dat een noot wordt aangezet - ZONDER deze aan te slaan, wordt daarmee een eerder - aangezette noot UITgezet! Deze uitzondering is bij alle - instrumenten bekend en wordt zelfs meer gebruikt dan de - offici�le methode van uitzetten. - - Wanneer uw instrument u dus vertelt een noot aan te zetten - met een velocity van 0, bedoelt hij niets meer dan een - vorige noot (met uiteraard eenzelfde eerste databyte) UIT te - zetten. Tja, MIDI is zelfs qua uitzonderingen een - volwaardige taal! - - - P O L Y P H O N I C K E Y P R E S S U R E - - Begint een statusbyte met een Ah, dan wordt daarmee de zgn. - polyfonische toetsdruk (in Engels polyphonic keypressure) - geregeld. Een moeilijk woord en een even moeilijk begrip, - waarvoor we bij de uitleg zelfs naar niet-elektronische - instrumenten moeten kijken. Eenieder, die ooit een (goede) - uitvoering van het muziekstuk 'Il Silenzio' heeft mogen - aanhoren, heeft kunnen horen dat de trompet de lange noten - aan het einde laat 'trillen'. [Nvdr. De functie MOD van - MoonBlaster doet hetzelfde.] Nu wilden de muziekmakers, dat - dergelijke effecten ook via MIDI aan te sturen waren. De - MIDI-makers, niet al te beroerd, voerden dus de polyfonische - toetsdruk in. Wanneer bij een (duurder) instrument na het - aanslaan van een toets nog eens extra op de toets gedrukt - wordt (bij de instrumenten spreekt men van aftertouch), kan - men een extra effect aanroepen. Dit extra effect is meestal - het trillen van de toon, maar in tegenstelling tot wat veel - mensen menen, is dit NIET standaard! Er bestaan ook wel - instrumenten, die de toonKLANK veranderen wanneer er - 'door'gedrukt wordt, bijvoorbeeld sommige duurdere - synthesizers. - - In MIDI werkt de polyfonische toetsdruk alsvolgt: Eerst - uiteraard de statusbyte (A0h t/m AFh) gevolgd door twee - databytes. De eerste databyte geeft aan welke noot het - effect krijgt, de tweede databyte de hoeveelheid effect. - - PAS OP: De noot hoeft niet aan te staan! Een leuk resultaat - is te krijgen door een bepaalde noot dit effect te geven - ZONDER dat deze eerst is aangezet. Elke volgende keer dat - deze noot wordt aangezet krijgt de noot nu automatisch dit - effect. Op deze manier kun je bijvoorbeeld een valse piano - imiteren. Die toets die vals moet klinken geef je polyfonic - keypressure en elke volgende keer dat deze toets wordt - aangeslagen, zal het geluid 'gek' doen (het nut van deze - truuk is vrij beperkt, maar ach, het is er ��n...). - - - C O N T R O L C H A N G E - - Begint een statusbyte met een Bh (dus het hexadecimale getal - B, voor alle duidelijkheid...) dan betreft het een Control - change. Dit statusbyte is zonder twijfel ��n der - krachtigsten van MIDI. Alle effecten, die niet een eigen - statusbyte hebben, maar wel door verschillende instrumenten - moeten worden begrepen, hebben hier hun basis gevonden. - - De Control change is een lijst van effecten (in Engels: - Controls), die gebruikt kunnen worden om uw conversatie met - uw instrument levendig te maken. De twee databytes die - het statusbyte (dus B0h t/m BFh) volgen geven - achtereenvolgens het soort effect en de 'zwaarte' van dat - effect aan. Daar deze MIDI-boodschap (in MIDI-jargon - MIDI-event genoemd) zo enorm krachtig is, ben ik van zins in - een volgend artikel hierop verder in te gaan. Voor nu kan ik - dus alleen maar zeggen: Als uw MIDI-kennis nog nul is, blijf - dan in 's hemelsnaam van deze boodschap af. De kans dat uw - keyboard iets verstaat, dat u absoluut niet wilt, is - huizenhoog aanwezig. - - - P R O G R A M C H A N G E - - Hier belanden we op de grens van de grammatica en steken we - de brug over naar de vocabulaire. Maar eerst nog even de - grammatica: Het statusbyte (C0h t/m CFh) wordt gevolgd door - slechts ��n databyte. Dit databyte is het MIDI-equivalent - van de vocabulaire. Met dit databyte geef je je keyboard - namelijk te kennen WAT voor geluid deze dient te maken. - - Maar pas op! Tot voor kort had elke producent (en vaak ook - elk instrument) zijn eigen vocabulaire. Dit was zo ontstaan - omdat van oorsprong de program change bedoeld was om - veranderingen aan te brengen in het geluid van synthesizers - zonder geheugen. Toen echter de instrumentmakers de - beschikking kregen over geheugen, zodat een hoeveelheid - standaard-geluiden vooraf al in het instrument opgeslagen - konden worden, werd dit MIDI-event meer en meer gebruikt om - een geluid (afhankelijk van producent patch, programma, - timbre of preset genoemd) te kiezen. - - Maar daar iedere producent zijn eigen voorkeur had voor - geluiden, was de lijst met geluiden ook op ieder instrument - anders. Een standaard was op dit gebied dus (tot voor kort) - ver te zoeken. De situatie was vergelijkbaar met talen, die - wel dezelfde grammatica kenden (dus zinsopbouw), maar heel - andere woorden gebruikten. - - Echter zoals al twee keer kort opgemerkt, is deze toren van - Babel langzaam maar zeker aan het verdwijnen. Een aantal - jaren geleden kwamen de grootste producenten van - instrumenten namelijk overeen om in het vervolg elke waarde - van het databyte eenzelfde instrument te laten selecteren. - Dit betekent geenszins, zoals zo velen menen, dat nu ook - alle keyboards van willekeurig welke producent hetzelfde - KLINKEN! Het betekent alleen dat wanneer je als databyte een - 0 geeft alle instrumenten voortaan een piano-klank laten - horen. Het verschil in klankopwekking is niet veranderd, - zodat een piano op een Yamaha-instrument nog steeds heel - anders (beter...?) klinkt dan op een Casio. Deze standaard - wordt de GM-standaard genoemd, wat staat voor GENERAL MIDI. - - Voor Roland ging deze standaardisatie nog lang niet ver - genoeg en daarom voerden zij de GS-standaard in. Een - GS-instrument is 'upwards compatibel' met een GM-instrument, - net zoals bij de MSX-systemen het MSX2-systeem upwards - compatibel was met het MSX1-systeem (met die uitzondering, - dat bij MIDI de compatibiliteit WEL 100% is) en een minister - wel begrijpt wat een bouwvakker zegt, maar zelden - omgekeerd... - - Op deze twee systemen kom ik een volgende keer terug, daar - dit een bron is van veel, heel veel misverstanden! - - - C H A N N E L P R E S S U R E - - Een statusbyte beginnend met een Dh regelt de channel - pressure, een eenvoudig alternatief voor de polyphonic - keypressure. Toen MIDI ontstond dacht men voor aftertouch - (zie polyphonic keypressure) twee alternatieven nodig te - hebben; een duur (de polyphonic keypressure) en een goedkoop - (de channel pressure). Dit vanwege het feit dat - drukreceptoren onder toetsen een dure aangelegenheid was (en - is!) en dus niet alle producenten �lke toets een eigen - receptor wilden geven. Helaas is het momenteel zo, dat de - polyphonische aftertouch in enorm weinig instrumenten - ingebouwd is en praktisch alle producenten voor de goedkope - variant hebben gekozen. - - Wat MIDI-betreft is het verschil tussen de polyphonic - keypressure en de channel pressure opvallend klein, nl. ��n - databyte. Waar de polyphonic keypressure twee databytes (��n - voor noot en ��n voor hoeveelheid) kent, kent de channel - pressure maar ��n databyte, nl. de hoeveelheid. Het effect - geldt daarna voor alle toetsen (of noten op hetzelfde - MIDI-kanaal, vandaar de naam 'channel pressure' dat - 'kanaaldruk' betekent). Voor de compleetheid dien ik nog op - te merken, dat de polyphonic keypressure door maar weinig - instrumenten wordt begrepen (m.u.v. de GS-instrumenten, waar - het standaard is dat ze polyphonic keypressure kunnen - ontvangen, maar - tot nu toe - geen enkele het uitzendt). - - - - Deel 2 van deze tekst kunt u in het submenu vinden - - - - - - - Deel 1 van deze tekst kunt u in het submenu vinden - - - - P I T C H B E N D C H A N G E - - Nu word ik melancholiek. De Pitch-bender... Wat mij betreft - HET effect, dat de mooiste resultaten kan hebben, maar - tegelijkertijd een liedje volledig kan afbreken. Mensen die - ECHT goed met pitch bend kunnen werken, zijn zeldzaam. Maar - vooruit, niet gedroomd, uitleggen! De pitch bend change - heeft als statusbyte de getallen E0h t/m EFh (dus beginnend - met een Eh). Na dit statusbyte dienen twee databytes te - volgen. De eerste voor de fijnafstemming (LSB) en de tweede - voor de grofafstemming (MSB). Eigenlijk dienen beide - databytes als ��n 14-bits getal gezien te worden, waarbij - het tweede databyte voorop staat. Het bereik is in dit geval - dan ook niet van 0 t/m 127, maar van -8192 t/m +8191! Het - nulpunt ligt bij 64 en 0 (dus eerste databyte 64, en tweede - databyte 0). - - Het resultaat van deze MIDI-boodschap is alles behalve - standaard! Bij Yamaha bijvoorbeeld doet een volledige - uitslag (beide databytes 127) de toon een vol oktaaf - verhogen, terwijl bij Roland slechts 2 halve tonen! Hierin - komt bij de GM-standaard geen verbetering, maar bij de - GS-standaard van Roland wel. Bij de GS-standaard is het - namelijk mogelijk via de control changes genaamd NRPN (Non - Registered Parameter Number) de 'Pitch bend sensitivity' (in - Nederlands de 'gevoeligheid van de pitch bender (sorry, geen - Nederlands alternatief voorhanden)' genaamd) te veranderen - van 0 halve noten tot 24 halve noten (= twee oktaven). De - uitleg ziet u terug in het artikel over GS/GM, de - MIDI-getallen geef ik u hier, zodat diegenen die een - GS-instrument bezitten kunnen gaan experimenteren. - - PAS OP: c = het gewenste MIDI-kanaal (standaard staat elke - upper-part van een GS-instrument op kanaal 4, dus c=3) en x - is de hoeveelheid halve noten, die met de pitch bend - maximaal wordt veranderd: - - Bc 101 0 Bc 100 0 Bc 6 x - - De statusbytes (steeds Bc) zijn hexadecimaal! Wilt u deze - code bijvoorbeeld met behulp van een Music Module naar uw - keyboard sturen op kanaal 4, dan laadt u onderstaand - programma (MIDI.BAS) in waarbij u op de plaats van de c het - gewenste MIDI-kanaal invult en op de plaats van de x het - aantal halve noten: - - 10 out 0,3 : out 0,21 ' = initialisatie MIDI van de MusMod - 20 out 1,&HBc : out 1,101 : out 1,0 - 30 out 1,&HBc : out 1,100 : out 1,0 - 40 out 1,&HBc : out 1,6 : out 1,x - - Gaat u ooit zelf met behulp van MIDI muziek maken en in uw - muziekstuk met pitch bend werken, gebruik dan ALTIJD de - pitch bend sensitivity (ook al herkent uw instrument deze - niet) en vergeet niet aan het eind van uw liedje de pitch - bend sensitivity ALTIJD weer terug te zetten op 2 (dit geldt - trouwens voor alle veranderingen die u in uw muziekstuk - maakt: zet ze aan het eind weer terug)! - - - S Y S T E M M E S S A G E S - - De system messages hebben als overeenkomst dat ze allen - beginnen met een Fh en geen databytes nodig hebben. Voor het - overige zijn deze statusbytes het zwarte schaap van de - MIDI-familie: Ze zijn de uitzondering op zo ongeveer elke - MIDI-regel: - - Het tweede (en uiteraard tevens laatste) getal van de - statusbytes heeft GEEN betrekking op MIDI-kanalen. De system - messages hebben altijd betrekking op het hele instrument. - - De system real time messages mogen NOOIT in een muziekstuk - worden verwerkt en zijn louter bedoeld om de communicatie - tussen instrumenten te bevorderen. - - Voor meer informatie verwijs ik u naar een volgend artikel, - daar over dit onderwerp hele boeken zijn volgeschreven! - - - R U N N I N G S T A T U S - - Dan tot slot nog een opmerking over de zgn. running status. - Net zoals in onze taal bij een opsomming datgene waar iets - over gezegd wordt mag worden weggelaten, mag dit ook bij - MIDI. Een voorbeeld: - - 'De fiets is groen, rijdt prettig, heeft een stalen frame.' - is hetzelfde als: 'De fiets is groen, de fiets rijdt - prettig, de fiets heeft een stalen frame.' - - In MIDI mag dit ook. In plaats van steeds dezelfde - statusbyte te moeten herhalen, hoeft deze slechts ��n keer - (in het begin uiteraard; een MIDI-zin dient nu eenmaal met - een statusbyte te beginnen) genoemd te worden. Mocht u dus - ooit denken bij een conversatie met uw instrument 'Tjonge, - wat gebruikt-ie toch veel databytes', dan is uw instrument - dus bezig met een opsomming en dient u elke keer het - statusbyte erbij te denken. - - Van belang is dus ook het aantal databytes dat normaliter op - een gegeven statusbyte volgt: - - C0h 1 2 3 4 5 6 7 8 9 10 - - betreft 10 MIDI-boodschappen, terwijl - - B0h 1 2 3 4 5 6 7 8 9 10 - - er slechts 5 betreffen! Mocht u dit niet meteen begrijpen, - denkt u er dan aan dat C0h slechts ��n databyte behoeft en - B0h twee! - - - T O T S L O T - - In dit artikel heb ik geenszins beoogd volledig te zijn. - Daarvoor is dit artikel ook in eerste instantie niet - bedoeld. Ik heb alleen maar een basis willen geven om verder - te gaan met MIDI en u er op attent willen maken, dat MIDI - een TAAL is en ook als zodanig behandeld zou behoren te - worden. En net zoals niet elk mens zal begrijpen wat ik hier - schrijf, zal ook niet elk instrument hetzelfde begrijpen van - een MIDI-boodschap. Dat hoort nu eenmaal bij MIDI en is - eigenlijk ook het grootste voordeel van MIDI. - - Daarom blijf ik altijd weer sceptisch staan tegenover het - gebruik van zgn. drivers om alle instrumenten hetzelfde te - laten begrijpen. Naast het feit dat u ten eerste uw - instrument te kort doet (elk instrument heeft zijn - specifieke voordelen, die niet met drivers te ondersteunen - zijn) is het ten tweede onmogelijk om echt alle instrumenten - hetzelfde te laten begrijpen. - - Als voorbeeld voor deze stelling wijs ik alleen maar naar - het pitch bend probleem, zoals ik dat behandeld heb bij het - verhaal over de pitch bend change. Het is toch ook niet - mogelijk om elk mens over de hele wereld dezelfde taal te - laten spreken! En mocht dit ooit tot de mogelijkheden gaan - behoren, dan zullen er direct weer per streek verschillen - ontstaan. In Nederland hebben we talloze woorden om neerslag - aan te duiden (regen, motregen, hagel, sneeuw, stortbui - enz.), terwijl in de woestijn aan dergelijke begrippen - totaal geen behoefte is! Daar hebben ze weer veel meer - behoefte aan woorden die bruin aangeven... - - Mocht u naar aanleiding van dit artikel nog vragen hebben - over MIDI, dan verwijs ik u graag naar een boek dat - geschreven is door Christian Braut, getiteld "Het complete - MIDIboek - Theorie en praktijk" en wordt uitgegeven door - Sybex. Loop eens binnen bij uw plaatselijke bibliotheek en - blader het eens door of ga eens kijken bij uw boekhandel, - waarbij ik eerlijkheidshalve wel dien op te merken dat het - boek niet goedkoop is! - - Ruud van Gestel diff --git a/sunrise_special/5/Make and change directory.md b/sunrise_special/5/Make and change directory.md deleted file mode 100644 index 3df5d44..0000000 --- a/sunrise_special/5/Make and change directory.md +++ /dev/null @@ -1,34 +0,0 @@ - M A K E A N D C H A N G E D I R E C T O R Y - - - Het programma MCD.COM is gemaakt om de volgende combinatie - te vereenvoudigen: - - MD \UTILS\INPAK - CD \UTILS\INPAK - - Met MCD wordt dit dan: - - MCD \UTILS\INPAK - - De subdirectory INPAK wordt gemaakt in de directory \UTILS - en de huidige directory wordt ingesteld op \UTILS\INPAK. - - - B A T C H F I L E - - De programmeur van MCD.COM heeft echter niet gedacht aan de - mogelijkheid van een batchfile. De volgende twee regels - hebben immmers hetzelfde effect als de COM-file: - - MD %1 - CD %1 - - En als je deze 2 regels invoert in een batchfile genaamd - MCD.BAT, is de werking precies hetzelfde, op ��n ding na: de - mogelijkheid om de directory meteen hidden te maken. - - By the way, MCD.COM is gemaakt door Fokke Post en zit in de - file MCD.PMA, die op deze disk staat. - - Kasper Souren diff --git a/sunrise_special/5/Memman Bugje.md b/sunrise_special/5/Memman Bugje.md deleted file mode 100644 index 076ff36..0000000 --- a/sunrise_special/5/Memman Bugje.md +++ /dev/null @@ -1,186 +0,0 @@ - - B U G J E I N M E M M A N - - - Deze tekst heb ik gedownload uit BBS Roefsoft. Omdat ik - aanneem dat dit ook interessant is om te weten voor - niet-MST'ers, plaats ik hem. Noot: de tekst is als brief - gericht aan het MST. - - Kasper Souren - - - Geachte programmeurs, - - Bij het maken van TSR's ben ik op een vreemd probleem - gestuit. Misschien ligt het aan mij, maar daar ben ik - ondanks dat ik mijn .GEN file flink heb doorzocht, niet - zeker van. - - Ik krijg ik te maken met vastlopers als ik mijn TSR of - ScrFade dubbel probeer te laden. Misschien lopen ook andere - TSR's vast, ik heb alleen bij deze twee dit opgemerkt. - Uiteraard kijken deze TSR's of ze zelf al zijn - ge�nstalleerd. - - - G E D R A G V A N M I D I X - - MIDIX (mijn TSR) is een TSR die 50 keer per seconde het - Philips-keyboard afscant, omzet naar MIDI data (er kunnen - verschillende "zones" worden gedefineerd), en deze naar - MIDI-out stuurt (nog niet gebufferd). Alle MIDI-IN data - wordt in een ISR (Interrupt service routine) gebufferd, en - deze buffer 50x per seconde door de TSR geleegd. De data - wordt multitimbraal over de 9 Module-kanalen gespeeld. E�n - MIDI-kanaal wordt gebruikt voor drumsamples. - - Overgens werkt de TSR prima, het reloceren en afbuigen in - DOS werkt nu perfekt, alleen wilde ik (in de toekomst dus) - als er dubbel ge�nitialiseerd werd, checken of de oude MIDIX - onder DOS was ge�nitialiseerd, en zo niet, de DOS-interrupt - alsnog goed afbuigen. De adressen in de heap kunnen dan via - een TSRCall naar de oude MIDIX worden opgevraagd. Maar dat - kan nu dus niet. - - - W A N N E E R L O P E N Z E V A S T - - ScrFade en MIDIX lopen allebij vast als ze voor de tweede - keer wordt geinstalleerd, en MIDIX.TSR reeds was geladen. - Overgens heb ik ook eens een redirection error met wat - vreemde tekens gezien nadat ik in BASIC MIDIX WEL twee keer - heb kunnen laden, het kan dus zijn dat ik of MemMan ergens - in het geheugen heeft zitten knoeien, terwijl hij daar geen - recht had. Overgens gebruikte ik MemMan 2.31 en 2.42 (uit - Waterland), DOS 2.22 van MK, en een 1024 kB Memmory mapper - in slot 1, op een VG 8235/00, niet dat wat uitmaakte, want - ook onder MSX-DOS 1 zonder MemMapper, ging het dubbel laden - fout. - - - S Y M P T O N E N - - ScrFade: Laat in een gruwlijk tempo de kleuren wisselen. - Beeld niet om aan te zien, TV lijkt kapot. - Midix: Laat een vreemd gekraak uit de module komen, hier heb - geen verklaring voor. - - Dit duidt er volgens mij op dat de interrupt continue wordt - aangeroepen, TsrMan staat continue te racen. Eigenlijk zou - dan ScrFade in no-time de tijdslimiet gehaald hebben, en dan - het scherm zwart moeten HOUDEN, toch? - - Mijn intialisatie routine ziet er zo uit: - - Init: - ld b,GetMemManEnt ;Ask for MemMan entry - ld de,256*'M' + Info ;Call the MemMan info - ; function - call ExtBio ;Through the ExtBio hook - ld (MemManEntry+1),hl ;Save the MemMan entry - ; address - ; - ld hl,TTsrName ;Pointer to TSR name-string - MemMan GetTsrID ;See if this TSR already - ; exists - jp nc,InitDouble ; Yes, => Double installed - ; error - - .comment / - Initialisatie routine die Heap-ruimte aanvraagt, een stukje - in de de initialisatieroutine aanpast, naar de Heap LDIRt, - FD9Ah afbuigt, en, indien na het bekijken van 00038h, - bepaalt of de TSR vanuit een DOS-omgeving werd geladen. Zo - ja, wordt de JP instructie waarnaar 0038h Jumpt, afgebogen - naar een ISR, die ook in de heap staat. / - - ; einde initalisatie - ld de,OK etc - ld a,2 - ret - ; - InitDouble: - ld de,TDouble - ld a,3 - ret - ; - TDouble: - db "You're not under MSX-DOS, I can't refresh " - db "DOS-MIDI interrupt routine." - dw CrLf - db "Under basic, MIDI-interrupts are almost always " - db "fast enough." - dw CrLf - TTsrName: TsrName - db " was already installed. Old MIDIX still exists." - dw CrLf - db 0 - - Dit zou bij een dubbele installatie probleemloos moeten - werken. Vreemd is dat ik na het eerste keer laden van - MemMan, probleemloos iedere willekeurige TSR kan laden, tot - een Segment full error volgt. - - - M O E I L I J K D O E N I K D E H E A P - - Op een MIDI-int moet de computer elke 1200 cycli (3.58 MHz - Z80) kunnen reageren. Inschakelen van een TSR-segment zal - dan te lang duren, dus heb ik in de Heap een stukje - code+buffer gereloceerd. Als er te weinig Heap-ruimte is, - wordt de buffer automatisch kleiner gemaakt. - - Onder DOS haal ik deze snelheid nog steeds niet, omdat DOS - altijd de BIOS eerst aanschakelt, voordat hij 00038h - aanroept. Hiervoor heb ik de DOS-interrupt JP instructie in - page 3 omgebogen naar mijn routine in de heap, waar nu - uiteraard het een en ander gePUSHt moet worden. Nadat - vastgesteld is dat het een MIDI interrupt is, wordt deze - afgehandeld, en zonder pardon weer EI en RET gegeven, dit om - de VDP-interrupt in het BIOS te vermijden. Mocht er een - MIDI- en VDP-interrupt tegelijk plaatsvinden, dan komt de - VDP vlak na EI RET met een interrupt voor de VDP, waarna - MIDIX hem gewoon via het BIOS laat lopen. - - - I D E E - - Misschien kunnen jullie in MemMan ook dit soort hooks - implementeren, voor snelle RS232- en modem-buffers. Een - nadeel dat ik nu heb, is dat ik in een Kill-routine - programma's die na mij ge�nstalleerd zijn en ook op mijn - manier te werk zijn gegaan, mijn Heap-ruimte niet mag - teruggeven, omdat zij er zonder pardon mijn heapruimte als - trampoline gebruiken. En ik kan er zeer moeilijk - achterkomen, waar zij zich afzetten om bovenop mijn heap te - springen... - - Misschien kan ik een FASTINT.TSR maken, wat dan een - aanvulling op MemMan is. FastInt zou ook in Mst TsrUtils of - worden ingebakken. Deze zou dan de Fast-Interrupt routines - kunnen beheren, aankoppelen en afkoppelen, als ze even niet - nodig zijn. Misschien kan hij ook helpen hij het reloceren - van routines in de heap en aanvragen van bufferruimte. (Oh - ja, is een TSR nou een Hij of een Zij? [Nvdr. Als het niet - bekend is, is het een Hij!] - - Ook zouden parameters bij TL, een teruggeef-tekstje bij TK, - ROMs als segment-code, een Memory-in-bytes-manager voor - nauwkeuriger geheugenbeheer (Pop-up database, scherminhoud - opslag) en een debugging-tool voor TSR's handig zijn. Een - functie voor het opvragen van het segment van een TSR zou - hierbij ook wonderen doen. - - Helaas werkt MSX-Debugger v2.0 (prachtig...) helaas niet zo - makkelijk met MemMan. Heb ik eindelijk via een TsrCall en - GetCurSeg het Segment-no van mijn TSR, voer een USE1 uit, - luistert MSXDEBUG niet meer... Ook een breakpoint in een - ongebruikte hook zetten, die ik aanroep vanuit mijn TSR, - werkt niet... - - Veel geluk/succes/(nog prettige feestdagen? of zijn die al - geweest?) met jullie prachtige MemMan project, van jullie - lastige beller, - - Mark-Jan Bastian diff --git a/sunrise_special/5/Picture packer.md b/sunrise_special/5/Picture packer.md deleted file mode 100644 index e00891f..0000000 --- a/sunrise_special/5/Picture packer.md +++ /dev/null @@ -1,104 +0,0 @@ - P I C T U R E P A C K E R - - - Vorige keer was er iets behoorlijk mis gegaan met de picture - packer. Op SRS#4 stond namelijk een verouderde versie van - het programma, zodat sommige dingen die ik in de handleiding - had vermeld niet werkten, omdat ze niet in het programma - waren opgenomen! - - Op deze disk vindt u - hoop ik - de goede en iets snellere - versie van het programma. Dat betekent wel, dat uw plaatje - gepackt met de oude versie niet meer kan worden bekeken met - de nieuwe. Maar ik vond dat de voordelen van deze nieuwe - versie groot genoeg waren. - - - D E B E D I E N I N G - - Deze tekst stond ook op SRS#3, maar goed. Eerst dient - KUN-BASIC ingeladen te worden. (Via DOS of met BLOAD, dat - ligt aan uw versie. Mensen met KUN-BASIC ingebouwd, tikken - invoudigweg CALL BC.) [Nvdr. Of gewoon _BC of helemaal niks - voor mensen die KUN-BASIC in ROM hebben zitten.] - - Om een plaatje te packen start u vervolgens PICPACKR.BAS op. - Het programma vraagt om de te packen filenaam. Als uit de - extensie al duidelijk is, in welk schermtype het plaatje - staat, (zoals bij .SC8 of .S12) stelt het programma dit zelf - in en bewaart dit later ook in de PCD file, zodat u het - plaatje altijd in het juiste schermtype kunt bekijken. - - Indien het niet te achterhalen is, vraagt het programma u in - welk schermtype de plaat behoort te staan. Als het packen - gelukt is kan het programma vragen, of het plaatje "high" - geladen moet worden. Later meer hierover. Daarna vraagt het - programma of het oude plaatje verwijderd moet worden. Het is - met de nieuwe versie WEL mogelijk om plaatjes weer in hun - oorspronkelijk formaat terug te zetten! (Zie info over de - depacker.) - - - B E K I J K E N E N T E R U G Z E T T E N - - Om plaatjes te bekijken of weer terug te zetten in hun - normale vorm laadt men PICDPACKR.BAS. Na het starten geeft - het programma een overzicht van alle PCD's in de huidige - directory. U hoeft nu alleen de filenaam zonder de extensie - PCD in te typen. - - Als u een piep hoort, betekent dat, dat het plaatje "hoog" - in het schermgeheugen staat. Het plaatje wordt nu getoond. - Typt u S als hij klaar is, dan wordt het plaatje gesaved met - dezelfde filenaam, maar met de extensie .SC7 .SC8 of .S12 - voor respectievelijk SCREEN 7, 8 en 12 plaatjes. U kunt het - plaatje nu weer gewoon met BLOAD ,S inladen. Typt u P, dan - savet (wat een woord) het programma het plaatje met de - extensie .PIC zodat u het met Designer Plus [Nvdr. en andere - rotte programma's] gelijk kunt inladen en bewerken. - - Nog even wat "technische" informatie. Om plaatjes te packen - moeten ze in een vorm staan zoals ze met BSAVE ,S worden - bewaard. De indeling van de eerste bytes van een PCD zien er - als volgt uit: - - 00H altijd waarde 224 (=alpha) - 01H geeft aan of plaatje hoog of laag in het geheugen staat - 108 (="L") is laag en 104 (="H") is hoog. - 02H deze byte bevat het schermnummer waarin het plaatje - staat. - 03H - .. zijn ongebruikt. Hier kan nog aanvullende info komen. - .. - 09H - 0Ah het begin van het plaatje - - Opmerking: er staat nergens hoelang de PCD is. De depacker - kijkt gewoon, of het scherm (0000H-D3FFH) vol is. - - Als het plaatje hoog in het VRAM wordt geladen wordt bij - deze indeling gwoon D400H opgeteld. D401H bevat dan 104. Het - hoog laden heeft als nut, dat bij het depacken slechts 1 - page wordt gebruikt en ook nog iets sneller is. - - Het lijkt me niet alt te moeilijk, om van deze programma's - ook een machinetaal versie van te maken, zodat het nog veel - sneller werkt. Wie? - - - V O L G E N D E K E E R - - Op die vectorgraphics maker zult u nog even moeten wachten. - Ik heb na drie maanden wachten EINDELIJK het boek te pakken - gekregen dat mij misschien verteld hoe ik onzichtbare lijnen - ook onzichtbaar moet laten worden. (Wat een smoes...) - - Volgende keer een spraaksynthese programma dat, jawel, - NEDERLANDS praat! Wel met een Frans accent (ja accent - spreekt-ie ook goed uit) maar het was oorspronkelijk een - Frans programma. Alleen nog even maken dat hij ook woorden - als "mooie" goed uitspeekt... (mooieju) - - Groeten! - Randy Simons - \ No newline at end of file diff --git a/sunrise_special/5/R800 rom ram lezen.md b/sunrise_special/5/R800 rom ram lezen.md deleted file mode 100644 index 8b80d53..0000000 --- a/sunrise_special/5/R800 rom ram lezen.md +++ /dev/null @@ -1,53 +0,0 @@ - R 8 0 0 R O M / R A M L E Z E N - - - Met het volgende BASIC-programmaatje heb ik even het - snelheids-verschil tussen ROM- en RAM-gebruik van de R800 - gemeten. (Staat op disk onder de naam TESTER.BAS.) - - 100 TIME=0 - 110 _TURBO ON - 120 FOR I=0 TO 16384 - 130 IF I/100=I\100 THEN LOCATE 0,0: PRINT I/100 - 140 NEXT I - 150 PRINT TIME - - Regel 130 kan natuurlijk veel beter. I/100=I\100 kan - namelijk worden vervangen door I MOD 100=0. Het "\" teken - staat voor integerdeling. Met MOD is de rest te bepalen van - een integerdeling. Maar doordat ik "/" gebruik duurt het wat - langer, en zijn de resultaten nauwkeuriger. - - - T A B E L L E T J E - - | RAM | ROM - ------------+------+------- - Z80 | 2074 | 2075 - ------------+------+------- - R800-ROM | 255 | 1000 - ------------+------+------- - R800-DRAM | 246 | 981 - - - De getallen zijn de resultaten bij mijn turbo R op 60 Hz. - Bij RAM heb ik KUN-BASIC in RAM (de diskversie dus) gebruikt - en bij ROM KUN-BASIC in een ROMmetje. - - Het valt direct op dat er een groot verschil is tussen RAM - en ROM bij de R800-modes. In de R800-modes is hij gemiddeld - 3.95 keer langzamer, terwijl het in de Z80-mode geen ene - moer uitmaakt. - - De conclusie uit deze cijfertjes is niet moeilijk te - trekken: bij het lezen van ROM schakelt de engine terug naar - de Z80-mode! - - Als je dus toevallig KUN op EPROM hebt, kun je toch nog - beter KUN in het geheugen inladen, omdat dat het zaakje 4 - keer versnelt in de R800-mode. Het maakt overigens niks uit - of dat geheugen het DRAM geheugen is (met READKANA - erinladen) of de gewone memory mapper. Wel vrees ik dat ook - een externe langzamer wordt aangestuurd. - - Kasper Souren diff --git a/sunrise_special/5/Rekenen op Z80.md b/sunrise_special/5/Rekenen op Z80.md deleted file mode 100644 index ed64322..0000000 --- a/sunrise_special/5/Rekenen op Z80.md +++ /dev/null @@ -1,611 +0,0 @@ - R E K E N E N O P Z 8 0 - - - Vaak kijk ik met afgunst naar de MC68000. Deze fraaie - processor kan hardwarematig vermenigvuldigen en delen. De - R800 kan alleen dat eerste, maar doet dat toch redelijk - snel. De Z80 kent geen van beide en is daarmee vreselijk - beperkt. Vermenigvuldigen is nl. een zeer elementaire - rekenkundige aktie en is bij het minste of het geringste - nodig. Voor de Z80 zijn er daarom speciale vermenig - vuldigingsroutines bedacht. Zo is er in de MSX bv. de Math - Pack die ook nog vele andere rekenkundige funkties kent. - - Voordelen van de Math Pack: - - Groot bereik in berekeningen - - Grote nauwkeurigheid mogelijk - - Nadelen: - - Zo traag als een jichtige slak - - Dat traagheid van de Math Pack maakt hem per definitie - ongeschikt voor bv. toepassing in demo's. Omdat ik toch wat - wiskundige geintjes in ML wilde maken was het dus - noodzakelijk om snel te kunnen vermenigvuldigen. Ik ben toen - aan het programmeren geslagen met als resultaat een stel - .... trage vermenigvuldigingsroutines. Een paar maanden - later keek ik weer eens naar deze routines en besloot om het - nog eens te proberen. De resultaten van dat werk zijn in dit - artikel te vinden. - - - D E T H E O R I E - - Er zijn twee manieren om twee getallen met elkaar te - vermenigvuldigen. De eerste is wat je vroeger in de eerste - klas lagere school deed; herhaald optellen. - - Vb. 10 * 4 = 40 - 10 + 10 + 10 + 10 = 40 - - Eenvoudiger kan niet. Een praktische routine zal met deze - methode erg klein worden, maar wordt erg traag als de - lusteller (4 in het voorbeeld) groot wordt. De - berekeningstijd is dus sterk afhankelijk van de invoer en - kan ook nog eens extreem oplopen. Het nut van deze - berekeningsmethode is dus zeer beperkt. - - Een betere methode is de volgende: - - Vb: 10 * 4 - - 10 = A = 00001010B 4 = B = 00000100B - - Bit A - 0 0 C = B*2^0 * 0 = 4*01*0 = 0 - 1 1 C = B*2^1 * 1 = 4*02*1 = 8 - 2 0 C = B*2^2 * 0 = 4*04*0 = 0 - 3 1 C = B*2^3 * 1 = 4*08*1 = 32 - 4 0 0 - 5 0 C = B*2^5 * 0 = 4*32*0 = 0 - 6 0 0 - 7 0 C = B*2^7 * 0 = 4*128*0= 0 - -- + - 40 - - Als je niet ziet hoe het werkt, probeer het dan eens met - andere getallen. Indien een bit in A hoog is wordt bij het - antwoord B*2^bitnummer_van_A opgeteld. De voordelen t.o.v. - de eerste methode liegen er niet om: - - Berekeningstijd is maar weinig afhankelijk van de invoer. - - Levert snelle korte code op. - - Het zal dan ook niemand verbazen dat dit een veel gebruikte - methode is. Een vermenigvuldiging in PASCAL of C zal meestal - zo uitgevoerd worden. - - - 8 B I T S V E R M E N I G V U L D I G I N G E N - - R O U T I N E 1 - - ; A = B.C - A=BMLC: LD A,0 ; 7 - BMLC.0: ADD A,C ; 4 - DJNZ BMLC.0 ; B<>0 THEN 13 ELSE 8 - RET ; 10 - - De getallen achter de instrukties stellen het resp. aantal - klokpulsen dat de instruktie duurt voor. Met deze gegevens - is nu een formule op te stellen over de duur van een - berekening. - - t = init + B * luslengte + exit + wait states - - MSX is helaas behept met een wait state. Dat houdt in dat de - Z80 na elke instruktie 1 klokpuls wacht voordat doorgegaan - wordt. deze vertraging is daarom ook in de berekening - opgenomen. - - t = 7 + 17B - 5 + 10 + 2 + 2B - = 19B + 14 - - t = Tijdsduur van routine in klokpulsen - 7 = LD A,0 - 17B = B * (ADD A,C + DJNZ label) - -5 = Laatste DJNZ correctie die 5 klokpulsen sneller is. - 10 = RET - 2 = LD A,0 en RET wait states - 2B = ADD A,C + DJNZ label wait states - - Het aantal microseconden dat de routine duurt kan eenvoudig - gevonden worden door t door 3.57 te delen. - - - R O U T I N E 2 - - ; A= A.C - A=AMLC: LD B,8 ; 7 - EX AF,AF ; 4 - LD A,0 ; 7 - EX AF,AF ; 4 - AMLC.0: RRCA ; 4 - JP NC,AMLC.1 ; 10 - EX AF,AF ; 4 - ADD A,C ; 4 - EX AF,AF ; 4 - AMLC.1: RLC C ; 8 - DJNZ AMLC.0 ; B<>0 THEN 13 ELSE 8 - EX AF,AF ; 4 - RET ; 10 - - twc = 'worst case' berekeningstijd (A = 11111111B) - = 22 + 8(14+12+21) - 5 + 14 + 62 - = 31 + 376 + 62 - = 469 - Twc = 469/3,57 = 131 us (microseconden) - - tbc = 'best case' berekeningstijd (A = 00000000B) - = 22 + 8(14+21) - 5 + 14 + 38 - = 31 + 280 + 38 - = 349 - Tbc = 349/3,57 = 98 us - - Omdat de berekeningstijd altijd afhankelijk is van de invoer - (maar in mindere mate dan bij routine 1) is er een worst en - best case berekening nodig. - - De routine begint met (22) en eindigd (14) met een aantal - instrukties. Daarnaast is er ook nog de loop die per - definitie 8 keer doorlopen wordt. Het aantal klokpulsen van - de lus moet dus met 8 vermenigvuldigd worden. De laatste - loop duurt echter 5 klokpulsen korter en deze worden weer - bij het resultaat afgetrokken. Natuurlijk moeten ook hier de - wait states weer bij de berekening betrokken worden. - - Het kan echter nog beter dan dit. - - R O U T I N E 3 - - ; A = A.C - A=AMLC: LD D,A ; 4 - LD A,0 ; 7 - LD B,8 ; 7 - AMLC.0 RRC D ; 8 - JP NC,AMLC.1 ; 10 - ADD A,C ; 4 - AMLC.1 RLC C ; 8 - DJNZ AMLC.0 ; B<>0 THEN 13 ELSE 8 - RET ; 10 - - twc = 18 + 8(18+4+8+13) - 5 + 10 + 44 - = 23 + 344 + 44 - = 411 - Twc = 411/3,57 = 115 us - - tbc = 18 + 8(18+8+13) - 5 + 10 + 36 - = 23 + 312 + 36 - = 371 - Tbc = 371/3,57 = 104 us - - Deze routine heeft slechtere best case prestaties dan - routine 2, maar de worst case prestaties zijn beter. Deze - twee getallen liggen ook dichter bij elkaar dan bij routine - 2 waardoor de berekeningstijd dus constanter is. Daarmee is - routine 3 beter dan routine 2. - - Routine 1 is sneller dan routine 3 indien: - - 14 + 19B = 411 - 19B = 397 - B = 20.9 ==> 21 - - Sneller indien B<21 (worst case) - - - 1 6 B I T S V E R M E N I G V U L D I G I N G E N - - Bij deze manier worden niet twee 16 bits getallen met elkaar - vermenigvuldigd, maar een 8 bits en een 16 bits getal. Een - echte 16 bit * 16 bit vermenigvuldiging levert een veel - tragere routine op en is daarmee vaak ongeschikt. - - - R O U T I N E 4 - - ; HL = B.DE - BMULDE: LD HL,0 ; 10 - B.DE.0 ADD HL,DE ; 11 - DJNZ B.DE.0 ; B<>0 THEN 13 ELSE 8 - RET ; 10 - - t = 10 + B(11 + 13) - 5 + 10 + 2 + 2B - = 26B + 17 - - - R O U T I N E 5 - - ; HL = A.HL - AMULHL: LD B,8 ; 7 - LD DE,0 ; 10 - A.HL.0: RRCA ; 4 - JP NC,A.HL.2 ; 10 - EX DE,HL ; 4 - ADD HL,DE ; 11 - EX DE,HL ; 4 - A.HL.1: ADD HL,HL ; 11 - DJNZ A.HL.0 ; B<>0 THEN 13 ELSE 8 - EX DE,HL ; 4 - RET ; 10 - - twc = 17 + 8(14 + 19 + 11 + 13) - 5 + 14 + 36 - = 542 - Twc = 542/3,57 = 152 us - - tbc = 17 + 8(14 + 11 + 13) - 5 + 14 + 36 - = 366 - Tbc = 366/3,57 = 103 us - - - R O U T I N E 6 - - ; HL = A.DE - AMULDE: LD B,8 ; 7 - LD HL,0 ; 10 - A.DE.0: RRCA ; 4 - JP NC,A.DE.1 ; 10 - ADD HL,DE ; 11 - A.DE.1 SLA E ; 8 - RL D ; 8 - DJNZ A.DE.0 ; B<>0 THEN 13 ELSE 8 - RET ; 10 - - twc = 27 + 8(14 + 11 + 29) - 5 + 51 - = 505 - Twc = 505/3,57 = 142 us - - tbc = 27 + 8(14 + 29) - 5 + 43 - = 409 - Tbc = 409/3,57 = 115 us - - - N E G A T I E V E G E T A L L E N - - De genoemde routines zijn ongeschikt voor negatieve - getallen. Indien de hoogste bits van beide invoergetallen - nl. als tekenbit gebruikt worden, zal overflow natuurlijk om - de haverklap optreden. Jammer genoeg is het voor bv. - vectorgraphics wel van essentieel belang dat met negatieve - getallen gerekend kan worden. Het is echter wel mogelijk om - de routines wat uit te breiden waardoor dit probleem - opgelost wordt. - - Het is niet helemaal waar dat de routines niet met negatieve - getallen om kunnen gaan. In het geval van routine 6 mag A - bij invoer niet negatief zijn, maar DE wel. Dit komt omdat - DE per lus alleen maar met 2 vermenigvuldigd wordt, waarbij - eventuele overflow geen invloed heeft. Dat levert voor - routine 6 de volgende routine op. - - ; In : A , Integer parameter 1 - ; DE, Real parameter 2 - ; Out: HL, Real antwoord - SAMLDE: BIT 7,A - JP Z,AMULDE ; (Met LD B,7) - NEG ; Maak A positief - CALL AMULDE ; (Met LD B,7) - LD DE,0 - EX DE,HL - OR A - SBC HL,DE ; Inverteer antwoord - RET ; omdat A ook ge�nverteerd is. - - Deze methode heeft drie consequenties: - - De routine wordt wel iets trager (meer 'overhead') - - Het bereik wordt verschoven naar -32768 tot 32768 - - De loopcounter in AMULDE kan nu van 8 naar 7 gezet worden - omdat bit 7 van A altijd 0 zal zijn. Hierdoor wordt de - extra overhead weer teniet gedaan. - - Met deze routine erbij is het gebruik van negatieve getallen - geen probleem meer, terwijl het geheel amper trager zal - worden. - - - Het volgende deel van dit artikel staat in het submenu. - - - - Het eerste deel vindt u in het submenu. - - - P R A K T I S C H G E B R U I K - - Het grote nadeel van alle genoemde routines is dat het - bereik t.o.v. de Math Pack relatief klein is. Daar komt nog - bij dat het moeilijk is om op overflow fouten te testen. - Dergelijke tests zijn niet ingebouwd omdat dat de routines - aanzienlijk trager maakt. Je kunt je dus afvragen wat het - pratische nut van de routines is. Welnu, dat hangt - natuurlijk helemaal van de applicatie af. Zo kan bv. - worteltrekken beter via de Math Pack gedaan worden. Is het - de bedoeling dat een kogeltje in een schietspel in een - rechte lijn van punt A naar punt B gaat, dan zijn juist deze - routines weer uitermate geschikt. - - Een groot nadeel is dus het feit dat je door het kleine - bereik enorm op overflow situaties op moet passen. Zou je in - routine 6 de getallen 200 en 400 met elkaar - vermenigvuldigen, dan is dat al meer dan 65535 (het - theoretische maximum). - - Overflow is echter te voorkomen door alleen maar 8 bits - getallen met elkaar te vermenigvuldigen. Het produkt van 2 - 8-bits getallen kan nl. maximaal 16 bits groot zijn. De - genoemde 8x16 bits routines kunnen dus het beste als 8x8 - bits routines gebruikt worden. Overflow is dan onmogelijk. - De 8x8 bits routines hebben met hun 8 bits antwoord nog wel - last van overflow. - - Het gebruik van deze routines moet in de grafische omgeving - gezocht worden. Neem bv. SCREEN 5, waar de maximale - resolutie 256x256 pixels is. Omdat de resolutie binnen 8 - bits past is het dus mogelijk om de vermenigvuldigingen voor - bv. pixeleffekten en zelfs vectorgraphics te gebruiken (elk - pixel valt binnen het bereik van de routines). - - - A L T E R N A T I E V E G E T A L N O T A T I E - - Het vermenigvuldigen van twee integers (een heel getal - tussen 0 en 255) is geen enkel probleem met deze routines, - maar daar bereik je niet veel mee. Om een goed praktisch - gebruik mogelijk te maken is een andere zienswijze op - hexadecimale getallen nodig. - - 1000H = 16*256 = 4096 - Dit klopt als een bus, maar wat gebeurt er als we een komma - midden in het hexadecimale getal zetten ? - - 10,00H = 16,00 = 16 - Ook dit is geen probleem. We beschouwen het HI-byte van het - getal als integer en het LO-byte als fraktie. Hiermee is de - mooie 16 bits integer verandert in een 16 bits real. - - Als we de zaken nu eens omdraaien. Hoe representeer je het - getal 13,5 (decimaal) in hexadecimale vorm ? - - 13,5 = 0D80H - 13 = 0DH, dit lijkt me geen probleem. - 0,5 = 80H, dit is wat lastiger. - - Een integer in hexadecimale notatie heeft dezelfde waarde - als dezelfde integer in decimale, binaire of elk ander - willekeurig talstelsel. Hoe anders is dit bij een breuk, - waar het getal achter de komma afhankelijk van het - talstelsel is. - - Als we twee getallen achter de komma afspreken (dat past nl. - mooi in ��n byte), dan kan een decimaal getal dus 100 - mogelijke frakties hebben (0,00 t/m 0,99) en een - hexadecimaal getal 256 (0,00 t/m 0,FF). De omrekening van - een decimale naar een hexadecimale fraktie gebeurt door de - decimale fraktie met 2,56 te vermenigvuldigen. - - Vb: 0,5 ==> 50 ==> 50*2,56 = 128 ==> 0080H - 0,5 ==> 0,5*256 = 128 ==> 0080H - - 20,23 decimaal is dan 143BH (afgerond) - 10,25 decimaal is dan 0A40H - (Ter vergelijking: 1025 decimaal = 0401H) - - Het leuke is dat een hexadecimale fraktie 2,56 keer zo - nauwkeurig is als een decimale (256 mogelijkheden i.p.v. - 100). - - De mogelijkheden die het gebruik van een fraktie met zich - mee brengt zijn buitengewoon aardig. Om te beginnen kunnnen - we nu een integer tussen 0 en 255 vermenigvuldigen met een - waarde die ligt tussen 0,0 en 0,FFH in stappen van 0,01H. - Indien ook negatieve getallen mogelijk zijn loopt het bereik - van -80,00H t/m 7F,FFH. Een praktische aanroep ziet er als - volgt uit. - - LD A,200 - LD DE,&H0040 - CALL AMULDE - (HL is nu 3200H, H = 32H = 50) - - Deze routine voert de berekening 200*0,25 = 50 uit. Let op - dat overflow niet voorkomt omdat twee 8 bits getallen - vermenigvuldigd worden tot een 16 bits antwoord. Bij het - antwoord is H het getal voor de komma en L de fraktie achter - de komma. - - - N E G A T I E V E F R A K T I E S - - Ook met deze getalrepresentatie zijn negatieve getallen - mogelijk. Het inverteren van een reeds naar een fraktiegetal - omgezette decimaal gaat gelukkig op precies dezelfde manier - als het omzetten van een pure integer. - - Vb: 100 = 64H - -100 = 256 - 100 = 9CH - - 10,23 ==> 0A3BH - -10,23 ==> 10000H - 0A3BH = F5C5H - - Je moet hier dus wel oppassen dat ook de fraktie van een - negatief getal anders is dan die van hetzelfde positieve - getal. Het veranderen van de fraktie moet echter gebeuren - omdat de berekeningen anders in de soep lopen. Bovendien - kunnen positieve en negatieve getallen ook willeurig - opgeteld en afgetrokken worden. - - Vb: - 30,23 ==> 1E3BH - -20,75 ==> EB40H - ------ + ----- + - 9,48 097BH - - 7BH = 123 ==> 123/2,56 = 48 - - De extra code die nodig is om met bv. routine 6 negatieve - getalberekeningen mogelijk te maken werkt ook met deze - getalnotatie (het zou niet best zijn als dat niet zo zou - zijn). - - - L I J N T J E R E K E N E N - - Omdat we aannemen dat DE een breuk is, is het nu bv. - mogelijk om een lijn te 'berekenen', wat overeen komt met - een punt dat door berekening in een rechte lijn van punt A - naar punt B gaat. Dat gaat als volgt. Een lijn kan gezien - worden als de schuine zijde van een rechthoekige driehoek. - Daarmee heeft een lijn dus een delta X en een delta Y. We - nemen deze even gelijk en stellen dat we een lijn willen - tekenen van coordinaat (0,0) tot (49,49). - - LD B,0 ; Lusteller - LUS: PUSH BC - LD D,0 ; DE loopt van 0,0 tot 0,FFH - LD E,B - LD A,50 ; = delta X = delta Y - CALL AMULDE - LD A,H - CALL PSET ; Teken pixel op coord. (A,A) - POP BC - DJNZ LUS - - Dit theoretische programmaatje zal 256 punten berekenen - tussen de coordinaten (0,0) en (49,49). Wat er feitelijk - gebeurt is dat delta X en delta Y per lus met een oplopend - getal vermenigvuldigd worden dat tussen DE=0 en DE=00FFH - ligt. Na de vermenigvuldiging staat de rest in register L, - maar die waarde is hier niet van belang (je kunt immers - tussen twee pixels niet nog een pixel tekenen). Let op dat - wanneer een lijn getekend wordt van (0,0) - (5,5), er ook - 256 punten berekent worden. Er worden dus 256/5 pixels op - dezelfde positie berekend! Om dat probleem op te kunnen - lossen moet je maar eens aan Piet Apegras denken (lengte van - schuine zijde). - - - I N T E G E R S D E L E N - - Delen is niets anders dan vermenigvuldigen met het - omgekeerde. Dat klinkt heel simpel, maar dat valt praktisch - wat tegen. Dit is overigens zeer recente informatie. Ik heb - de delingsmethode die ik hier ga noemen pas bedacht toen ik - met dit artikel bezig was (er ging mij een lichtje op). - - Vb: - - 50 / 13 = 3,8462 - Maar ook: 50 * 1/13 = 3,8462 - - De deling kan uitgevoerd worden door de vermenigvuldigen met - 1/13 i.p.v. delen door 13. Aangenomen dat we alleen maar - integers door integers willen delen (met een real als - antwoord) kan een tabel gemaakt worden met de waarden 1/2 - t/m 1/255. Gebruik makend van de bij onze vermenig - vuldigingen toegepaste fraktie zal die tabel er als volgt - uit zien. - - 1/002 = 0,50 - 1/003 = 0,67 - 1/004 = 0,25 - 1/010 = 0,10 - 1/100 = 0,01 - 1/110 = 0,00... - 1/128 = 0,00... - 1/200 = 0,00... - 1/255 = 0,00... - - Bij de wat grotere delers blijkt dat twee getallen achter de - komma niet voldoende is. Vanaf 1/101 zal het antwoord altijd - 0 zijn. Je begrijpt, een deling zal op deze manier bijna - nooit kloppen. Met twee extra decimalen gaat het al stukken - beter. 1/253 wordt dan 0,0040 en 1/255 wordt 0,0039. Een - omzetting naar een hexadecimale fraktie levert nu echter ook - een 16 bits getal op dat echter wel 2,56 keer zo precies is. - - De berekening in ons voorbeeld moet nu als volgt uitgevoerd - worden: - - 50/13 = 32H/13 - - 1/13 ==> (1/13)*256*256=5041 == 13B1H Er moet 2 keer met 256 - vermenigvuldigd worden omdat we een 4 decimalen nauwkeurige - fraktie willen hebben. Het antwoord is nu een 16 bits - fraktie. - - Berekening gaat nu als volgt: - - 32H * B1H = 2292H - 32H * 13H = 03B6H - ------- + - 03D8H - - Terugrekening naar decimalen: - D8H = 216 ==> 216/256 = 0,8438 - 03H = 3 ==> 3 - ------ + - 3,8438 - Met de rekendoos: 50/13 = 3,8462 - ------ - - Absolute fout: -0,0024 - - Het verschil wordt veroorzaakt door de 92H van de eerste - berekening die verwaarloosd wordt en afrondingsfouten bij - het omzetten van decimaal naar hexadecimaal. Deze methode is - twee getallen achter de komma nauwkeurig en dat is precies - genoeg. - - Om te kunnen delen moet dus eerst een tabel gemaakt worden - met 16 bits frakties van de delingen 1/2 t/m 1/255 (delen - door 0 mag niet, en delen door 1 levert geen fraktie op). - Daarnaast moeten om ��n deling te doen twee - vermenigvuldigingen en een optelling gedaan worden. - - Indien de nauwkeurigheid van het antwoord niet van uiterst - belang is, kan de eerste vermenigvuldiging ook overgeslagen - worden (dus alleen 32H * 13H). De absolute fout is dan 1. - Vb: - 8000H - 02F0H - ------- + - 0370H - - Indien de eerste vermenigvuldiging overgeslagen wordt zou - het antwoord 02F0H zijn, zodat de absolute decimale fout 0,5 - zou worden. Het hangt van de applicatie af of dit gedaan kan - worden, maar het levert natuurlijk wel een behoorlijke - snelheidswinst op. - - Helaas is deze methode alleen maar geschikt om twee integers - te delen. Dat is dan ook meteen het nadeel van deze methode, - want het maakt nogal wat uit of je 200 door 1 of 1,9 deelt. - Hoe dit het uiteindelijke plaatje bij bv. vectorgraphics - be�nvloedt is mij (nog) niet bekend, maar ik kan me - situaties voorstellen waarbij de deling van alleen integers - te weinig nauwkeurigheid biedt. Helaas zal een routine die - twee 'real' 16 bits getallen deelt ontzettend traag worden. - - - C O N C L U S I E - - Gewapend met de vermenigvuldigingen en de deling is het nu - mogelijk om 'real-time' vector graphics te maken zonder - tussenkomst van de Math Pack. De echte vector freaks kunnen - hun hart dus weer eens ophalen. Ook het maken van een - fractal berekeningsprogramma is met deze routines mogelijk, - maar dat is al door XelaSoft gedaan. - - Als je deze berekeningsroutines eens aan het werk wilt zien, - dan moet je maar eens de Fuzzy Logic demo's 'Math Magicians' - of 'MB Musax 1' bekijken. De bestuurbare sterrenhemel in - deze produkten werkt op hetzelfde principe als de lijn - berekening. De delta X en Y zijn hier per lus echter - variabel waardoor de sterren kunnen draaien. Dit geintje - wordt dus NIET bereikt door een enorme tabel in het geheugen - op te slaan waar alle mogelijke posities in staan. Ook de - snelheid van de routines blijkt uit deze routines. In 1/60 - seconde worden nl. 64 vermenigvuldigingen uitgevoerd om 32 - sterren te besturen. - - - Alex van der Wal - F U Z Z Y L O G I C diff --git a/sunrise_special/5/Software projecten deel 1.md b/sunrise_special/5/Software projecten deel 1.md deleted file mode 100644 index f90ea00..0000000 --- a/sunrise_special/5/Software projecten deel 1.md +++ /dev/null @@ -1,450 +0,0 @@ - S O F T W A R E P R O J E K T E N D E E L 1 - - - Welkom bij deel 1 van de 'cursus' software projekten. Zoals - beloofd in de inleidende tekst gaan we vanaf nu wat dieper - in op de vraag wat men in elk systeem tegen komt en wat daar - aan te programmeren valt. In dit deel zal ik de problemen en - mogelijkheden van een standaard filesysteem behandelen. Een - filesysteem is een verzameling routines waarmee data van elk - denkbaar type geladen en verwerkt kan worden. Het moge - duidelijk zijn dat dit een zeer belangrijk onderdeel van elk - softwareprojekt is. Zo belangrijk zelfs, dat de kwaliteit - van de rest van het systeem sterk afhankelijk is van de - mogelijkheden van het filesysteem. - - Ik zal waarschijnlijk wel weer wat woorden door elkaar heen - gebruiken. Woorden als softwareprojekt en systeem, - softwarelagen en niveaus zijn synoniemen van elkaar. - - Een wat groter softwareprojekt heeft: - - invoer - - uitvoer - - programma code - - data - - - I N V O E R - - Dit kan natuurlijk van alles zijn. Bij een tekstverwerker is - het invoer van een toetsenbord, muis of joystick, maar ook - van een achtergrondgeheugen (diskette of harddisk etc.). Dit - zelfde geldt voor een tekenprogramma. Je kunt wel stellen - dat ELK groter programma achtergrondgeheugen gebruikt. - Daarom zal een eigen systeem een goed uitgedokterd - filesysteem nodig hebben. - - - U I T V O E R - - ELK programma [Nvdr. TSR's soms niet!] zal uitvoer naar het - scherm hebben. Zelfs het meest pietepeuterige programmaatje - heeft het al, dus dit is iets om rekening mee te houden. Als - het al mogelijk is om iets van achtergrond geheugen te - lezen, dan zal het schrijven daar naartoe ook wel handig - zijn. Bij een tekstverwerker of tekenprogramma is dit - natuurlijk vanzelfsprekend, maar het gemiddelde spel zal - daarentegen maar weinig naar achtergrond-geheugen schrijven. - - - P R O G R A M M A C O D E E N D A T A - - Ook dit is iets wat elk programma zal hebben. De problemen - die deze datavormen opleveren zijn per projektsoort anders. - Bij een tekstverwerker zal over het algemeen maar weinig - extra code bijgeladen hoeven te worden tijdens normaal - bedrijf, maar bij spellen is dat andere koek. - - - F I L E H A N D L I N G - - Uit deze beschrijvingen blijkt dat er altijd behoefte - bestaat om data van en/of naar een achtergrondgeheugen te - transporteren d.m.v. een filesysteem. Een standaard - filesysteem is daarom ook enorm handig is om altijd bij de - hand te hebben. Hoe vaak is het ons ook al niet overkomen - dat we voor elke demo nieuwe laadroutines hebben geschreven - omdat de oude plotseling niet meer handig bleken. Het - schrijven van dit soort code is 'dom' werk dat feitelijk zo - standaard hoort te zijn dat het maar ��n keer gedaan hoeft - te worden. Een filesysteem is zo'n cruciaal onderdeel van - elk softwareprojekt dat het daarom niet verkeerd is om dit - als eerste te schrijven van waaruit de rest van het systeem - kan groeien. Een filesysteem is als het ware de ruggegraat - van de rest van de software. - - Verder zijn laad- en saveroutines natuurlijk per direkt te - gebruiken om andere delen van je eigen systeem mee te maken. - Dus tijdens de ontwikkelfase kan je meteen al van deze - routines gebruik maken wat natuurlijk ontzettend handig is. - - - Wat zal het gemiddelde filesysteem moeten kunnen? - 1) Laden van data - 2) Schrijven van data - - Dat lijkt simpel genoeg, ware het niet dat de data zo - verschillend van aard kan zijn. Mogelijke datasoorten zijn - bijv.: - - Algemene data - - Code - - Graphics - - Paletten - - Sprite data - - Muziek - - Samples - - Samples en muziek zullen voor de gemiddelde tekstverwerker - van ondergeschikt belang zijn, maar ik vind het toch een - goed idee om een gezonde 'link' naar een eigen spel te - leggen. - - Algemene data en code zijn eigenlijk ��n en dezelfde tenzij - codefiles van het BLOAD type zouden zijn en de datafiles - niet. Het is verstandig om beide typen gelijk te kiezen, wat - nl. in code scheelt. - - Graphics hebben twee eigenschappen waardoor ze zich van - normale data onderscheiden: - - Ze kunnen gecruncht zijn - - Ze moeten uiteindelijk in VRAM terecht komen. - - Of je wel of niet gecrunchte graphics gebruikt, je zal RAM - nodig hebben om de grafische data tijdelijk in op te slaan - voordat het naar VRAM gekopieerd wordt. Praktisch kost dit - minimaal 16 kB, die voor de rest van de tijd voor andere - doeleinden te gebruiken is. Overigens is het ook heel goed - mogelijk dat er meerdere grafische formaten zijn. Dit kan je - het beste vergelijken met het COPY "filenaam.ext" en BLOAD,S - commando in BASIC. Beide zijn grafische laadroutines, die - echter verschillende dataformaten gebruiken. - - De andere filetypes: paletten, sprite data, muziek en - samples; het enige wat ze gemeen hebben is dat ze allemaal - een eigen specifieke behandeling nodig hebben. - - - B E S T E M E T H O D E V O O R D A T A - - Er blijken net zoveel datatypen als algoritmen om deze data - te verwerken te zijn. Of je nu dus wel of niet een standaard - filesysteem maakt, er zullen hoe dan ook routines geschreven - moeten worden om de verschillende datatypen af te handelen. - Met dat gegeven kunnen we meteen een stap verder gaan, want - wat zal er nu theoretisch moeten gebeuren als een file - geladen wordt? - - 1) Geef opdracht om de file te laden - 2) Ga naar de betreffende afhandelingsroutine - 3) Laad de file - 4) Handel laadfouten af - 5) Verwerk de geladen data - - Stel je voor dat je bij elk te laden file zelf al deze - akties uit zou moeten voeren, daar wordt je toch helemaal - krankjorem van. Nee, dan de goede oude BASIC tijd waarbij - het laden van een grafische file en het afhandelen van het - daarbij horende palet een fluitje van een cent was m.b.v. - twee eenvoudige commando's. - - Het zou buitengewoon wenselijk zijn om elke mogelijke file - van elk mogelijk type even simpel te kunnen laden als in - BASIC het geval is. In assembly krijg je dan zoiets als: - - LD DE,FILADR ; Adres van filenaam string - ; Geef met andere registers de laadpositie aan - CALL GETFLE ; HAAL file!! - JP C,oeps ; Uh oh, een laadfout. - : - : - - FILADR: DM "FILENAME","EXT" - - END - - - De routine GETFLE moet nu het genoemde rijtje van 5 taken - uit gaan voeren. Het soort file is bv. via de extensie door - te geven (.PIC voor graphics, .COD voor code, .MBM voor de - muziek etc.). Dit systeem is al zo oud als DOS zelf en - waarom zouden we hier recalcitrant gaan doen? Bovendien is - het ook een prima manier om de dingen voor jezelf te - administreren. - - De laad-algoritmen hangen natuurlijk sterk af van de manier - waarop je de data opgebouwd hebt. Laat ik een grafisch - voorbeeld geven. Bij ons [Nvdr. Fuzzy Logic] is grafische - data ALTIJD gecruncht en bestaat uit blokken van 16 kB die - per blok gedecruncht kunnen worden. Het laadalgoritme is dan - bv. als volgt: - - - Zet het VRAM decrunchadres - - Laad een blok in het RAM - - Decrunch dat blok vanuit de tijdelijke RAM opslag. - - Herhaal dit tot de file volledig in het VRAM - gedecruncht is. - - Hier komt nu het grote voordeel van een routine als GETFLE - naar voren. Zodra deze standaard routine eenmaal geschreven - is, kan het je niet meer schelen HOE een file geladen wordt, - maar alleen nog maar DAT dit gebeurt. Laden, decrunchen en - foutafhandeling; dit alles gebeurt automatisch zonder dat je - er verder nog last van hebt. Men noemt zoiets een - 'hi�rarchisch niveau' of 'software laag'. Het komt er op - neer dat het routines binnen verschillende softwarelagen - niets kan schelen HOE de ander nu precies zijn werk doet, - maar er gewoon vanuit kan gaan dat het gebeurt. In het geval - van graphics moet de gebruiker van de routine GETFLE: - natuurlijk wel weten dat een bepaald blok RAM van 16 kB - gebruikt wordt, maar dat is nog altijd een stuk eenvoudiger - dan dat je alles tot in detail moet weten en regelen. - - - Deel 2 van deze tekst kunt u in het submenu vinden. - - - - - PART B - - - S O F T W A R E P R O J E K T E N D E E L 1 - - - H I E R A R C H I S C H E N I V E A U S - - Hi�rarchische niveaus heb je in vele soorten en maten. In - principe is je computer zelf al een verzameling niveaus, - maar het hangt van je uiteindelijke doel af hoeveel daarvan - van belang zijn. Een mogelijk overzicht van deze niveaus is - bijv. als volgt: - - Niveau 0, Elektronen binnen componenten - Niveau 1, Transistoren, weerstanden etc. - Niveau 2, Logische bouwstenen (AND en OR funkties etc.) - Niveau 3, Complexe bouwstenen (zoals de CPU) - Niveau 4, CPU Microcode - Niveau 5, Machinetaalprogramma's - (Niveau 6, Hogere talen) - Niveau 7, Operating System - Niveau 8, Applicaties - - Overigens bestaat er niet een gedefinieerde toewijzing van - niveaus, en de toewijzing ervan is dan ook een twistpunt - tussen computerguru's. Een leuk aspekt is echter dat de - scheiding waar de hardware eindigt en de software begint per - type computer verschillend is. De ene computer bijv. kan wel - hardwarematig vermenigvuldigen en de andere niet. - - Je begrijpt dat de manier waarop de elektronen over de print - van je computer lopen voor de gemiddelde software applicatie - niet echt interessant is. Dit voorbeeld laat alleen maar - even zien hoe de verschillende niveaus opgebouwd KUNNEN - zijn. GETFLE zou in dit voorbeeld een niveau zijn binnen het - Operating System niveau, maar zelfs daar kan je over - twisten. - - Het hebben van dergelijke niveaus is echter cruciaal voor - het welslagen van een groot software projekt. Het stelt je - nl. in staat om de complexiteit van het probleem als geheel - te verdelen over meerdere (in principe ook wel los werkende) - modules. Indien je dit niet doet, zie je na een paar weken - programmeren de bomen door het bos niet meer en is je code - gegarandeerd een puinhoop geworden. Is dat het geval, stop - dan twee maanden (om je hoofd even leeg te maken) en begin - opnieuw; deze keer met een goede opzet. Overigens is het - onderscheiden van niveaus binnen je software niet expliciet - hetzelfde als modulair programmeren (waar ik het in het - verleden al eens over gehad heb en waarbij de Italiaanse - kookkunst uitgebreid aan de orde is geweest), maar de twee - gaan wel hand in hand samen. - - - A F H A N D E L I N G V A N F I L E T Y P E S - - Ik kan voor bepaalde standaard filetypes wel gaan behandelen - hoe je deze verwerkt, maar de meeste verwerkingsroutines - zijn gewoon sterk afhankelijk van hoe deze files zijn - opgebouwd. Deze routines zal je dus zelf moeten schrijven, - waarbij je van tevoren goed moet nadenken hoe je het jezelf - zo gemakkelijk mogelijk kunt maken. - - Neem nu een MoonBlaster muziekfile. Een datafile van dit - type mag in principe overal in het geheugen komen te staan. - Indien je dus geen vaste plaats voor .MBM files aanwijst zal - je dus elke keer aan de MoonBlaster afspeelroutine moeten - vertellen waar deze de data kan vinden. Het is een - peuleschil om dit binnen GETFLE te doen, het moet per - definitie gebeuren, dus waarom zou je dit dan niet standaard - doen binnen de afhandelingsroutine? Nadat nu een .MBM file - geladen is met GETFLE hoeft de muziek alleen nog maar - aangezet te worden en klaar is Kees. Het is hierbij wel - belangrijk dat de afspeelroutine standaard onderdeel van je - verzameling routines is, en dat geldt bv. ook voor een - mogelijke grafische data decruncher. Het voorbeeld met de - MoonBlaster file laat duidelijk zien dat je de verwerking - van zo'n file niet meer exact hoeft te kennen, omdat het - automatisch gaat. - - Hetzelfde geldt voor samples die naar de Music Module - gekopieerd moeten worden. Waarom zou je het zelf doen als - het ook automatisch kan? Laad via GETFLE gewoon een .MBK - file en laat GETFLE maar uitzoeken of er een MSX-AUDIO met - sample-geheugen aanwezig is en indien ja, de sampledata naar - deze herrieschopper kopi�ren. - - Als je de zaken een beetje slim aanpakt is het mogelijk om - dingen waar je in het verleden dagen mee hebt lopen stoeien - ('ik kan die samples niet laden omdat ik geen 16 kB vrij - geheugen heb' of 'waar staat die decruncher ook alweer?') nu - met ��n CALL instruktie vlekkeloos uit te voeren. Als dat - geen vooruitgang is weet ik het ook niet meer. - - - F I L E S Y S T E E M N I V E A U S - - Een routine als GETFLE: staat natuurlijk op een vrij hoog - niveau binnen je filesysteem. Daaronder zullen zich toch nog - minimaal twee niveaus moeten bevinden om je filesysteem te - completeren. - - Filesysteem niveaus: - - Niveau 0: Interface naar de BDOS en foutafhandeling. - Niveau 1: Laad- en verwerkingsroutines voor de verschillende - filetypes. - Niveau 2: GETFLE-achtige routine(s) - Niveau 3: Mogelijke batchverwerker - - - N I V E A U 0 - - In een eerder artikel op Sunrise Special #4 heb ik al eens - lopen zeuren over de moeizame interfacing met de BDOS. - Ikzelf heb de routines die in de bijbehorende listing van - dat artikel horen bijna letterlijk gebruikt als niveau 0 - voor mijn eigen filesysteem. In het algemeen kun je stellen - dat in niveau 0 routines moeten komen die delen van, of - complete files kunnen laden. Hierbij is de foutafhandeling - natuurlijk van groot belang. - - Wat je ook schrijft voor niveau 0, de routines zullen toch - ongeveer hetzelfde doel moeten hebben als de bij SRS#4 - gegeven routines (anders in het geen niveau 0 meer). - - - N I V E A U 1 - - Hier komen de routines die files van een bepaald formaat - laden en verwerken. In een stuk hierboven is al het ��n en - ander vermeld over de routines die hier terecht moeten - komen. - - - N I V E A U 2 - - In niveau 2 staat op dit moment maar ��n routine; te weten - GETFLE (of soortgelijke). Het is echter helemaal niet - ondenkbaar dat hier meer routines komen. In mijn eigen - systeem heb ik nog een eigen RAMdisk zitten en een aantal - van de routines om de RAMdisk te besturen zijn in niveau 2 - te vinden (de meeste echter in niveau 1). - - - N I V E A U 3 - - Een batchverwerker? Wat is dat? Welnu, dit is een - verzameling routines waarmee het mogelijk is om niet ��n - file (zoals bij GETFLE) maar meerdere files achter elkaar te - laden en te verwerken (denk aan .BAT files in DOS). Dit kan - vooral bij spellen wel eens enorm makkelijk blijken, waar - van tijd tot tijd meerdere files geladen moeten worden - voordat verder gespeeld kan worden. De 'Batch' is een - tekstbestand dat in de teksteditor van je keuze gemaakt kan - worden. In deze tekst staan dan commando's die de - batchverwerker interpreteert en uitvoert. Afijn, of en hoe - je zoiets wilt implementeren moet je zelf maar weten. Bij - mijn systeem is de batchverwerker wat uit de kluiten - gegroeid en bevat naast file laadcommando's nu ook een - aantal commando's om data op een hoger niveau te verwerken. - - - N I V E A U G E G E V E N S U I T W I S S E L I N G - - Het aantal gegevens dat tussen de verschillende niveaus - uitgewisseld wordt moet zo klein mogelijk gehouden worden, - maar we kunnen ook niet zonder. Hoe zou je anders in GETFLE - een foutmelding terug kunnen krijgen als deze helemaal niet - weet wat er in de onderliggende niveaus in gebeurt? Wat voor - parameters er ook aan een niveau doorgegeven of ontvangen - worden, ze zullen in elk geval door moeten geven of iets - goed of fout gegaan is. Dat kan het beste met de Cy (=Carry) - gebeuren. Om nu conversieproblemen tussen de verschillende - niveaus tegen te gaan is het van belang dat alle niveaus hun - foutmeldingen via de Cy doorgeven. - - Een Cy gegenereerd bij een fysieke laadfout in niveau 0 moet - dus bij alle andere niveaus ook bekend gemaakt worden. - Niveau 2 weet dan bijv. wel DAT er iets fout is gegaan maar - nog niet precies WAT. Dat is echter ook niet belangrijk - omdat het in niveau 2 helemaal niet interessant is wat er is - fout gegaan. Het enige dat telt voor de routine op niveau 2 - (GETFLE) is dat deze nu weet dat het niet 100% zeker is dat - de data die geladen had moeten worden ook daadwerkelijk op - de plaats van bestemming is aangekomen. Met dit gegeven zal - een beslissing genomen moeten worden of het nog eens - geprobeerd wordt, of dat het programma moet stoppen. - - Alleen binnen niveau 0 is bekend wat de bron van de - foutmelding moet zijn geweest. Hier zit immers de - foutafhandling en het kan best zijn dat alleen maar de disk - offline is wat binnen niveau 0 prima op te lossen is door de - gebruiker te vragen deze als de bliksem weer terug te - stoppen. Een foutmelding naar hogere niveaus hoeft dan - natuurlijk niet meer gegeven te worden. - - Of het nu om een filesysteem of andere vorm van hi�rarchisch - systeem gaat, het teruggeven van foutmeldingen betekent - altijd hetzelfde. Een routine die een foutmelding - terugkrijgt weet dat de gewenste verandering aan het systeem - (geheugen, disk, registers binnen een chip of elk ander - onderdeel van de computer) niet gelukt is. We praten hier - over 'inconsistentie' van het systeem; het niet langer weten - HOE elk systeemonderdeel ingesteld is. - - Wat er precies moet gebeuren als dit gebeurt is afhankelijk - van de programmeur en de situatie. Bij een echte fysieke - laadfout kan maar het beste met het programma gestopt worden - waarna een boodschap op het scherm moet komen dat je diskje - kapot is. Daarentegen zal een fout m.b.t. het niet kunnen - vinden van een muis in de meeste gevallen wel anders op te - lossen zijn. - - - T O T S L O T - - Simpel is dit alles zeker niet. Een goede voorbereiding is - essentieel voor het welslagen van elk programma. Ga nu niet - als een bezetene ondoordachte code schrijven, maar werk - eerst op papier uit wat er in de verschillende niveaus moet - komen en hoe dat er per niveau ongeveer uit zal komen te - zien. Vooral de manier van gegevens doorgeven (en welke - gegevens) tussen de verschillende niveaus is verschrikkelijk - belangrijk. - - In dit eerste deel zijn de basisonderdelen van een - filesysteem besproken alsmede de manier waarop je zoiets - moet struktureren. Het is helaas maar het topje van de - ijsberg, maar ik hoop toch een idee gegeven te hebben over - de globale opbouw. Ik geef expliciet geen code omdat - praktisch blijkt dat NIEMAND daar belangstelling voor toont. - Zelfs de grootste luiaards vinden dat ze nogmaals het wiel - moeten uitvinden, en wie ben ik om dat tegen te houden. - Bovendien, zelf zou ik waarschijnlijk hetzelfde doen en de - gegeven code hooguit als voorbeeld gebruiken. - - Volgende keer komen de programmeer- en ontwikkelomgevingen - aan de beurt. Deze twee zaken zijn nl. innig verweven, en - dat is iets om terdege rekening mee te houden. - - Tot de volgende keer! - - Alex van der Wal diff --git a/sunrise_special/5/Spelontwerp 2.md b/sunrise_special/5/Spelontwerp 2.md deleted file mode 100644 index 8d9a267..0000000 --- a/sunrise_special/5/Spelontwerp 2.md +++ /dev/null @@ -1,162 +0,0 @@ - S P E L O N T W E R P 2 ? - - - Ongeveer een week na het uitbrengen van een Sunrise Special - breekt bij ons thuis de hel los. De brievenbus heeft dan - plotseling last van chronische indigestie. Zozeer zelfs dat - de postbode speciaal met de wagen langs komt om de fanmail - in bulk af te leveren. Nog dramatischer zijn de taferelen - bij onze onrechtmatig gedigitaliseerde hoofdredacteur. Bij - hem wordt de fanmail op dergelijke dagen op pallets - aangeleverd. Dit nadat een dozijn postbodes hernia's hebben - opgelopen bij het afleveren van postzakken lofbetuigingen. - Bij deze wil ik (ook namens Kasper) al mijn fans bedanken - voor de vage bijschriften op mijn girorekening alsmede voor - de overvloedige huwelijksaanzoeken?? [Nvdr. Zoveel - vrouwelijke of (XOR) homofiele MSX'ers zijn er toch niet?] - - U ziet, enig cynisme is ons niet vreemd. Zelden of nooit - komt er ook maar ��n letter commentaar (positief of - negatief) op de door ons gegenereerde technische - computerromans. Je hebt meer kans dat je met je ogen dicht - intelligent leven in de ruimte ontdekt dan dat er ook maar - een vleugje van een reactie waar te nemen is na de produktie - van een SRS. - - Schertste daarom ook mijn verbazing toen ik een poos geleden - plotseling wel enthousiaste mensen op mijn stoep vond die - graag wilden dat ik meer over een bepaald onderwerp zou - schrijven. Het ging daarbij over een vermeende serie die ik - zou gaan maken met als thema: "het ontwerpen van een spel". - - Dat onderwerp had ik in een opwelling eens bedacht, en onder - het motto 'It seemed like a good idea at the time' ben ik - toen als een bezetene aan een 20 delige cursus begonnen. - Veel verder dan deel 1 ben ik echter nooit gekomen. De reden - daarvoor was dat alhoewel ik me wel een voorstelling kon - maken over hoe je zoiets aanpakt ik er nog geen serieuze - praktijkervaring in had. Feitelijk stond ik jullie dus de - les te leren over een onderwerp waar ik zelf niets van af - wist. Zelfs ik begrijp dat zoiets voorbestemd is om fout te - gaan en daarom heb ik toen besloten om met die onzin op te - houden. - - Heden doet zich echter de situatie voor dat die praktische - kennis wel aanwezig is. Door de dramatische reakties op mijn - eerste poging leek het me toch een goed idee om het - verdronken kalf uit de gedempte put te graven. In - tegenstelling tot de vorige keer zullen deze - softwaretechnische verhandelingen zich in eerste instantie - niet expliciet op het ontwerpen van een spel richten, maar - meer op randvoorwaarden die van belang zijn bij de - totstandkoming van een groot software projekt. Indien ik de - maanden die zullen komen niet aan een terminale situatie - onderworpen zal worden beloof ik plechtig om mijn uiterste - best te doen om een aantal samenhangende artikelen te - schrijven. - - - W A T G A A N W E D O E N E N W A A R O M ? - - Wat ik wil doen is het behandelen van een aantal problemen - die bij ELK groot software projekt aan de orde komen. Het - beste voorbeeld daarvan is bijvoorbeeld het beheren (en - beheersen) van data. Theoretisch is het zeer eenvoudig om - een geheugen van willekeurige grootte tot de nok te vullen - met relevante data, maar praktisch kleven daar wat haken en - ogen aan. Hoe onthoud je waar welke gegevens staan en hoe - zorg je er voor dat deze gegevens elkaar niet in de weg - zitten. Ook moet je er voor zorgen dat de uiteenlopende data - op het juiste moment op de juiste plaats aanwezig zijn, wat - dan ook nog met conversieslagen gepaard gaat (zoals het - decrunchen van grafische data). - - Hopelijk zie je al dat de te behandelen problematiek niet - van toepassing is op het gemiddelde BASIC programma, maar - eerder op het soort programma dat minimaal 128 kB nodig - heeft om te kunnen werken. Waarom zou zo'n groot programma - meer problemen veroorzaken dan het gemiddelde BASIC - programma? Dat heeft te maken met het feit dat de door het - systeem in ROM aangeboden routines voor dataverwerking - plotseling niet meer voldoende blijken. In BASIC kun je - vrolijk van legio voorgebakken commando's gebruik maken, die - dan in assembly plotseling niet meer eenvoudig voorhanden - zijn. - - Samengevat kun je stellen dat het nodig is om een eigen - 'systeem' van eigen voorgebakken routines te maken om een - groot project in assembly (of elke andere taal die niet - BASIC heet) te kunnen realiseren. Het door BASIC aangeboden - systeem is simpelweg niet langer bruikbaar. - - - De (voorlopig) te behandelen onderwerpen zijn: - - - Opbouw van het eigen systeem - o een standaard filesysteem en kennismaking met een aantal - relevante programmeerstrategie�n. - o programmeer- en ontwikkelomgevingen - * keuze van en eisen aan de omgeving - * mogelijkheden van een omgeving - * algemene opbouw - o geheugen management - o interrupt management - o opbouw van het geheugen - o debugging - - Bij de behandeling van deze onderwerpen zullen - waarschijnlijk geen programma's gegeven worden. De reden - hiervoor is dat praktisch blijkt dat een te beperkt aantal - mensen dat als nuttig beschouwd. - - Mochten er nu mensen zijn die denken: "Leuk, maar ik zou - graag ook wat over onderwerp 'X' willen weten", dan kan - hij/zij dergelijke wensen bij de redactie deponeren waarna - ik ze zal behandelen. - - De eerlijkheid gebied me te zeggen dat we (= Fuzzy Logic) - reeds beschikken over een dergelijk systeem. Dit systeem - (F-KERNEL genaamd) heeft een aantal mogelijkheden die het - uitermate geschikt maakt om bijv. een RPG mee te maken. Het - systeem gaat zo ver dat op de BDOS na ALLE funkties van de - MSX-BIOS zijn overgenomen. Ik vermeld het maar even om aan - te tonen dat ik niet weer uit mijn nek sta te zwammen - (alhoewel?) [Nvdr. Who cares? Nek-zwammen kan ook heel - interessant zijn!]. - - - T O T S L O T - - H�t grote voordeel van zo'n eigen systeem is dat het (indien - goed en doordacht ontworpen) herbruikbaar is voor van alles - en nog wat. Zodra je je eerste spel af hebt met zo'n systeem - is het volgende een makkie omdat je al een scala van - handige, snelle, ge�ntegreerde en bij de gebruiker bekende - routines hebt die veel 'dom' werk uit handen nemen. - Natuurlijk gaat het niet alleen om spellen, maar ook - utility's, muziekprogramma's en noem ze maar op kunnen met - dergelijke systemen gemaakt worden. De routines die - onderdeel maken van dat systeem moet je zien als een - aanvulling op het Operating System van je computer. De - routines die er in komen zijn de routines die JIJ makkelijk - in het gebruik vindt en die je vaak gebruikt. Samengevat kan - je zeggen dat een vast eigen systeem ervoor zorgt dat je - voor elk project niet opnieuw het wiel hoeft uit te vinden. - - De ge�nteresseerden kunnen hun hart nu ophalen door deel 1 - aan een kritisch onderzoek te onderwerpen dat ook op deze - disk aanwezig is. Bedenk echter wel dat geen commentaar van - de buitenwereld voor mij betekent dat er blijkbaar geen - animo voor dit onderwerp is. Ik ben voor veel zaken te - porren, maar lullen tegen spreekwoordelijke muren is daar - niet een onderdeel van. (Gek toch dat de Special zoveel - leden heeft, maar dat die nooit wat van zich laten horen.) - Wat ik persoonlijk erg leuk zou vinden is als bv. de makers - van D.A.S.S., Giana Sisters, Pumpkin Adventure of andere - professionele spellen of andere soorten programma's ook eens - iets over de door hun gehanteerde systemen zouden willen - melden. - - Voor nu, veel plezier en keep on MSX'ing - - Alex van der Wal diff --git a/sunrise_special/5/Sprites in ML deel 2.md b/sunrise_special/5/Sprites in ML deel 2.md deleted file mode 100644 index c72c330..0000000 --- a/sunrise_special/5/Sprites in ML deel 2.md +++ /dev/null @@ -1,273 +0,0 @@ - S P R I T E S I N M L 2 - - - - S P R I T E S I N D E P R A K T I J K - - Hier dan eindelijk het vervolg van de sprite besturingen in - ML. Het eerste deel kunt u vinden op Sunrise Special #2. - Om sprites daadwerkelijk op het beeld te toveren zonder - daarbij het MSX-BIOS te gebruiken is nogal een ingewikkeld - verhaal. In deel 1 hebt u kunnen lezen over de start - adressen voor de sprite data. Om enig inzicht te krijgen in - de VDP waarden, zal ik hier een aantal zaken van ophelderen - met enkele voorbeelden. - - - S P R I T E M O D E S - - Op een MSX2 of hoger zijn er nog meer zaken, wat betreft het - zetten van een sprite, waar rekening mee moet worden - gehouden. Zoals de kleuren en speciale commando bits. Daarom - spreken we van twee sprite modes: MODE 1 (MSX1 en hoger), - MODE 2 (MSX2 en hoger). Dus een MSX2 gebruikt zowel MODE 1 - als MODE 2. MODE 2 bestaat uit alle extra MSX2 functies. - - Sprite Mode 1: Graphic 1 (screen 1) - Graphic 2 (screen 2) - Multi colour (screen 3) - Max. sprites op 1 horizontale as: 4 - Sprite Mode 2: Graphic 3 (screen 4) - Graphic 4 (screen 5) - Graphic 5 (screen 6) - Graphic 6 (screen 7) - Graphic 7 (screen 8) - Max. sprites op 1 horizontale as: 8 - - - I N S T A L L E R E N V A N S P R I T E S - - Om sprites op het scherm te toveren, moeten eerst de - volgende register worden beschreven: - - Noot: Registers worden afgekord met "r# xx", hiermee worden - de registers aangeduid zoals ze in ML worden gebruikt. Dus - denkt er om MSX2 registers worden in BASIC 1 verhoogd. Dus: - VDP(12)=r#11!) - - b7 b6 b5 b4 b3 b2 b1 b0 - r# 1 x x x x x x SZ EXP(/MAG) (mode 1) - r# 8 x x x x x x SPD x (mode 1) - - SZ: SiZe. Grootte (0:8x8, 1:16x16) - EXP: EXPanded. Vergroting (0:normaal, 1:vergroot) - SPD: SPrite Display. Weergave (0:AAN, 1:UIT) - - Voorbeeld: - VDP(1)=VDP(1) and &B11111100 or &B00000010 - VDP(8)=VDP(8) or &B00000010 - - De sprite grootte is hier: 16x16 normaal (r#1). De sprites - worden zichtbaar op het scherm (r#8). - - - N O G M A A L S D E S P R I T E A D R E S S E N - - (zie ook deel 1) - - De volgende VDP registers worden hiervoor gebruikt: - - b7 b6 b5 b4 b3 b2 b1 b0 - r# 5 D14 D13 D12 D11 D10 1 1 1 (mode 1) - r#11 0 0 0 0 0 0 D16 D15 (mode 2) - r# 6 0 0 E16 E15 E14 E13 E12 E11 (mode 1) - - D10-D16: VRAM-adres voor spritekleur- en attribute tabellen. - E16-E11: VRAM-adres voor spritepatroon tabel. - - N.B. D10-D14: VRAM lijn adres - D15/D16: VRAM page nr. - E11-E14: VRAM lijn adres - E15/E16: VRAM page nr. - - Een beschrijving van de registers: - - r# 5 en r#11 vormen samen het adres waar de kleur- en - positie tabellen van de sprites. Bits 0-2 moeten altijd hoog - zijn. Bits 3-7 vormen het lijn adres van de kleur tabel. - Adres berekening: start-lijn * 128 or &H07. - - De startlijn is altijd in stappen van 8, dus kunnen er - feitelijk maar 32 verschillende waarden worden opgegeven. - - Voorbeeld: - - Stel we willen de sprite kleur data op Page 1, lijn 200 - plaatsten, dan worden r#5 en r#11: - r# 5, &HCF (200 or 7) - r#11, &H01 - - Hierbij is het kleur tabel adres bekend: 200x128 or 7=&H6400 - Het positie tabel adres: kleur tabel adres + &H0200 = &H6600 - - Standaard zijn deze registers gevuld met de volgende - waardes: - - r# 5, &B11101111/&HEF (VRAM adres: &H7400) - r#11, &B00000000/&H00 (VRAM page: 0) - - - r# 6 bevat het adres waar de patroon tabellen van de - sprites. Bits 0-3 vormen het lijn adres van de patroon - tabel. - Adres berekening: start-lijn * 128 * 16. De startlijn is - altijd in stappen van 16, dus kunnen er maar 16 - verschillende waarden worden opgegeven. Bits 4/5 bevatten - het pagina nummer. - - Voorbeeld: - Stel we willen de sprite patroon data op Page 2, lijn 32 - plaatsen, dan worden r#6: - r# 6, &H22 (32/2 or &H20) - (LSB: adres, MSB: page) - - Hierbij is de patroon tabel adres bekend: - 32*16+&H8000=&H8200. - De tabel bevindt zich boven de 32 kB (page1) dus moeten we - er &H8000 (=16 kB) bij optellen. - (als r#6>31 dan bovenste 64 kB VRAM.) - - Standaard is dit register gevuld met de volgende waarde: - r# 6, &B00001111/&H0F (VRAM adres: &H7800, page: 0) - - Het leuke van het kunnen verandereren van de sprite adressen - is dat je zonder alle sprite data hoeft te veranderen, toch - in 1 keer alle sprites kunt veranderen. - - - P L A A T S E N V A N S P R I T E S - - De sprite attribute tabel bevat de weergave waarden van de - sprites. Elke sprite wordt weergeven op 1 van de 32 "sprite - vlakken". De sprite waarden voor elk vlak bestaat uit vier - bytes. Het start adres hiervan wordt gezet door r#5 en r#11 - te beschrijven (VRAM adres: r#5/r#11 + &h0200). - - De vier bytes bevatten de volgende informatie voor 1 sprite - vlak: - +0 Y-positie De verticale positie van een sprite wordt - verhoogd met 1. Dus de werkelijk waarde die - moet worden geschreven is Y-1. Door deze - waarde op 208 (mode 1) of 216 (mode 2) te - zetten, wordt de sprite niet zichtbaar op - het scherm. - +1 X-positie Horizontale positie. Kan "slechts" 256 - waarde bevatten, dus in een hogere resolutie - (bijv. screen 7) zal de sprite altijd een - even waarde krijgen. - +2 Sprite nr. Bevat het sprite patroon, die moet worden - weer gegeven op dit vlak. - +3 Kleur Bevat de kleur van de hele sprite in sprite - Mode 1. Als er in Mode 2 wordt gewerkt, is - deze waarden onbelangrijk. Door het EC bit - (bit 7) hoog te zetten, wordt de sprite 32 - pixels naar links geschoven. - - Let op! deze waarden zijn bedoeld voor het sprite vlak. - Er zijn 32 vlakken, dus de totale lengte van de attribute - tabel is: 32 * 4 = 128 bytes. - - Voorbeeld: (8x8 sprites, niet vergroot, mode 1) - - We willen sprite 7 op vlak 11 plaatsen, met als positie - (40,50), en de kleur is 9. Eerst moeten we weten naar welk - attribute-adres we willen schrijven. We gebruiken vlak 11, - dus: 11 * 4 = 44. We weten het start adres al, door r#5/r#11 - te lezen. Dit is bijvoorbeeld: &H7600. - - Het schrijf adres wordt dan: &H7600 + 44 = &h762C. - Vervolgens beschrijven we de volgende VRAM adressen: - - &H762C+0, 50-1 (Y-1) - +1, 40 (X) - +2, 7 (nr) - +3, 9 (kleur) - - Door het EC bit te zetten wordt de sprite 32 pixels naar - links verplaatst. Het nut hiervan is dat deze sprite nu ook - pixel voor pixel aan de linker kant van het scherm kan - verdwijnen. Dat deze waarde 32 is, komt omdat een sprite - 16x16 vergroot kan wezen. Deze wordt dan immers 32x32 groot. - Ook deze sprite moet pixel voor pixel kunnen verdwijnen. - - Om een sprite daadwerkelijk op het scherm te kunnen - plaatsen, moeten er met nog een aantal zaken rekening worden - gehouden. Een van die zaken is de grootte van de sprite - (16x16). - - Als er voor 8x8 sprites wordt gekozen, levert dit geen - problemen op. Echter het gebruik van 16x16 sprites is iets - ingewikkelder. Om een 16x16 sprite te plaatsen, worden er - eigenlijk 4 (8x8) sprites geplaatst. Het totaal patroon ziet - er als volgt uit: - - X - Y +------++------+ - | spr || spr | - | +0 || +2 | - +------++------+ - | spr || spr | - | +1 || +3 | - +------++------+ - - Dus het totaal oppervlak wordt aangevuld met de 3 volgende - sprites. - Voorbeeld: (16x16 sprites, niet vergroot) - sprite patroon 3 moet worden geplaats op (10,20). - De eerste (8x8) sprite wordt dan: 3 * 4 = 12. - de opbouw wordt dan als volgt: - X=10 - Y=20 +--------------++--------------+ - |spr.12 (10,20)||spr.14 (16,20)| - +--------------++--------------+ - |spr.13 (10,36)||spr.15 (16,36)| - +--------------++--------------+ - - Om een 16x16 sprite te maken kun je dus net zo goed zelf 4 - (8x8) sprites plaatsen. Echter, 16x16 sprites hebben een - voordeel dat je maar een keer een X en een Y hoeft op te - geven, want de VDP regelt zelft de andere 3 (8x8) sprites. - - Om nu een (16x16) sprite te zetten, moet men er dus rekening - met het volgende houden: Het sprite nummer dat wordt - opgegeven moet uit stappen van 4 bestaan. Dus 0, 4, 8 etc. - - Wordt er bijvoorbeeld toch sprite 3 opgegeven, dan wordt dit - sprite patroon 0, en worden 8x8-sprites 0, 1, 2 en 3 - geplaatst. - - Bij vullen van de attribute tabel moet hier ook rekening mee - worden gehouden. Immers de 3 opvolgende sprite vlakken - worden ook gebruikt. Er zijn nus feitelijk 32/4=8 sprite - vlakken, waardoor er maar 8 sprites kunnen worden vertoond. - Dus om een sprite te zetten, wordt het adres van deze tabel - als volgt berekend: - - VRAM adres van r#5/r#11 + vlaknr * 4 * 4. - - De laatste vermenigvuldiging met 4 zorgt er voor dat de 3 - volgende vlakken worden overgeslagen, deze worden immers - automatisch door de VDP gevuld. Het vergroten van een sprite - (EXP) heeft geen gevolgen voor het berekenen van de - attribute tabellen. - - Voorbeeld: (16x16, vergroot (=32x32), mode 1) - - We willen een (16x16) sprite op vlak 3 plaatsen. X=132, - Y=40, sprite nr=0, kleur=7. De sprite moet 32 pixels naar - links worden verschoven. r#5/r#11= &H7600 - - Attribute adres: &h7600 + 3 * 4 * 4 = &H7630. - - &h7630+0, 40-1 (Y-1) - +1, 132 (X) - +2, 12 (nr: 3*4) - +3, &H87 (kleur + EC=1) - - Wat betreft het plaatsen van een sprite, moet er nu - voldoende voer zijn geleverd. Om het hele sprite verhaal af - te maken, wil ik volgende keer de aandacht richten op de - sprite botsingen (mode 1 �n 2), en de kleurcodes bij sprite - mode 2. Tot een volgende keer! - - Roman van der Meulen diff --git a/sunrise_special/5/Turbo Loader.md b/sunrise_special/5/Turbo Loader.md deleted file mode 100644 index 4979a0b..0000000 --- a/sunrise_special/5/Turbo Loader.md +++ /dev/null @@ -1,305 +0,0 @@ - T U R B O L O A D E R - - - Demo's op de Picturedisk bestaan vaak uit een groot aantal - files, en omdat de BDOS voor elke file opnieuw in de - directory en FAT moet gaan kijken waar de file precies - staat, duurt het laden relatief lang. - - De laadtijd kan enorm worden verkocht door voor de demo een - zogenaamde "turbo loader" te maken. Je zet dan alle files - achter elkaar in ��n grote file, en je maakt een klein ML - programmaatje dat alles inlaadt en op de juiste plek zet en - vervolgens het hoofdprogramma start. - - De naam "turbo" is zeker niet ten onrechte, want het laden - gaat zo veel en veel sneller dan wanneer alle files apart - moeten worden geladen. De enige manier om nog sneller te - laden is door alles op sector te zetten zoals ook bij de - Special wordt gedaan met de teksten, muziek en graphics, - maar dat is voor de Picturedisk erg onhandig. - - Ik zal het principe van de turbo loader, heel toepasselijk, - uitleggen aan de hand van de Witch's Revenge promo die ik - voor Sunrise Picturedisk #9 had gemaakt. - - - P L A K K E N - - We gaan de files met het DOS2 commando CONCAT aan elkaar - plakken. Zet eerst de benodigde files netjes bij elkaar op - een disk en geef ze zulke namen dat je ze met ��n filenaam - met wildcards exclusief kunt beschrijven. - - Dit klinkt misschien moeilijk, maar dat valt reuze mee. Noem - de files bijvoorbeeld DEMO.MBM, DEMO.MBK, DEMO.SC5, etc. Met - DEMO.* heb je dan alle files te pakken. Met "exclusief" - bedoel ik dat er geen andere files op de disk staan die niet - bij de demo horen maar die wel aan DEMO.* voldoen. - - In het voorbeeld had ik de volgende files: - - DRUMKIT DAT 5760 03-11-93 20:21 - GFX1 DAT 13568 03-11-93 20:18 - GFX2 DAT 12672 03-11-93 20:19 - MUSIC DAT 2304 03-11-93 20:22 - TEXT DAT 2048 04-11-93 16:49 - MBREPLAY DAT 4608 18-08-93 11:32 - - - We plakken deze files nu aan elkaar tot ��n grote file - WRPROMO.ALL van ca. 40 kB met het volgende commando (onder - DOS2!): - - CONCAT /B *.DAT WRPROMO.ALL - - Nu zien we de reden waarom ik de files zo heb hernoemd dat - ze met *.DAT beschreven kunnen worden, want met de - oorspronkelijke filenamen had het er zo uitgezien: - - CONCAT /B DRUMKIT.MBK + GFX1.SC7 + GFX2.SC7 + ... - - De /B is nodig om de files binair achterelkaar te zetten, - als je dat weglaat dan worden de files bij de eerste ^Z - afgekapt en dat is natuurlijk niet de bedoeling. - - Het is zometeen belangrijk dat je de volgorde en de lengtes - van de files bij de hand hebt, dit kan (wederom onder DOS2) - heel makkelijk met: - - DIR *.DAT > DIR.TXT - - In DIR.TXT staat nu de directory van de .DAT files. Met - behulp van deze file gaan we nu een ML progje schrijven dat - WRPROMO.ALL inleest. - - - D E L O A D E R - - Om de file in te laden gebruiken we de BDOS. We defini�ren - nu eerst een aantal functienummers en het BDOS aanroepadres: - - - BDOS: EQU &HF37D - SETDMA: EQU &H1A - OPEN: EQU &H0F - READ: EQU &H27 - - - Een BDOS functie kan worden aangeroepen door het - functienummer in register C te zetten en vervolgens het - adres &HF37D aan te roepen. - - We moeten nu eerst de file WRPROMO.ALL openen. We gebruiken - hiervoor de BDOS functie OPEN, waarbij DE naar het FCB moet - wijzen. FCB staat voor File Control Block. Een FCB is een - blokje van 37 bytes, dat als volgt is opgebouwd: - - FCB+0 drive (0 = default, 1 = A:, 2 = B:, etc.) - FCB+1 filenaam (8 karakters) - FCB+9 extensie (3 karakters) - FCB+14 record size (16 bits waarde) - FCB+33 random record (32 bits waarde) - - Er staat nog meer informatie in, maar die is voor ons nu - niet interessant. In de ML source ziet de FCB er als volgt - uit: - - - FCB: DB 0 - DM "WRPROMO ALL" - DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - DB 0,0,0,0,0,0,0,0,0,0 - - - Het openen van de file gaat nu als volgt: - - - LD C,OPEN ; open de file - LD DE,FCB - CALL BDOS - LD HL,1 - LD (FCB+14),HL ; record size - - - De recordsize wordt op 1 byte gezet, zo kunnen we elk - willekeurig stuk van de file inlezen. Door de waarde van - "random record" te veranderen kunnen we de diverse gedeeltes - van WRPROMO.ALL in een willekeurige volgorde inlezen, maar - het is het makkelijkste om het op de volgorde te doen waarin - ze in de file staan, want dan gaat het vanzelf goed. - - De eerste file is de drumkit, deze file is 5760 bytes lang. - Dit is een ingekorte drumkit van MoonBlaster, ik heb de rest - gewoon "weggegooid" omdat dat niet werd gebruikt. - - De eerste 56 bytes bevatten de sample adressen, die straks - in de MoonBlaster replayer moeten worden ingevuld. We laden - eerst deze 56 bytes in en bewaren ze zolang in een - buffertje. - - - LD DE,SMPBUF ; sample adressen - LD C,SETDMA - CALL BDOS - LD HL,56 ; aantal te lezen bytes - LD DE,FCB - LD C,READ - CALL BDOS - - - De functie SETDMA stelt het adres in waar de data naartoe - moet, dit adres moet in DE staan. De BDOS functie &H27 die - we hier gebruiken heeft als invoer HL en DE nodig. DE wijst - weer naar het FCB en in HL moet het aantal bytes staan. - - Nu gaan we de rest van de samplekit inladen. Omdat we de - MoonBlaster replayer nog niet hebben ingeladen, zetten we - die zolang op mapper page 2. - - - LD A,2 - OUT (&HFE),A - - LD DE,&H8000 ; samplekit - LD C,SETDMA - CALL BDOS - LD HL,5760-56 - LD DE,FCB - LD C,READ - CALL BDOS - - - Dit gaat weer precies hetzelfde. Nu zijn de graphics aan de - beurt. Ik gebruik mapper page 3 als laadbuffer. De lengte - van de eerste file met graphics is 13568 bytes, zo kunnen we - in de directory zien. - - - LD A,3 - OUT (&HFE),A - - LD DE,&H8000 ; gfx1 - LD C,SETDMA - CALL BDOS - LD HL,13568 - LD DE,FCB - LD C,READ - CALL BDOS - LD HL,0 - CALL DCRNCH - - - De graphics waren gecruncht en worden met de routine DCRNCH - (die ik hier niet bij heb gezet) gedecruncht naar VRAM-adres - &H00000. Het inladen van het tweede gedeelte van de graphics - gaat net zo: - - - LD DE,&H8000 ; gfx2 - LD C,SETDMA - CALL BDOS - LD HL,12672 - LD DE,FCB - LD C,READ - CALL BDOS - LD HL,&H8000 - CALL DCRNCH - - - Deze graphics worden naar adres &H08000 gedecruncht. Nu - laden we het muziekje in, dat op adres &H8000 in mapper page - 3 moet staan (mapper page 3 was al geselecteerd). - - - LD DE,&H8000 ; muziek - LD C,SETDMA - CALL BDOS - LD HL,2304 - LD DE,FCB - LD C,READ - CALL BDOS - - - Nu is de tekst aan de beurt. Eerst wordt de mapper - teruggezet. - - - LD A,1 - OUT (&HFE),A - - LD DE,&HB000 ; tekst - LD C,SETDMA - CALL BDOS - LD HL,2048 - LD DE,FCB - LD C,READ - CALL BDOS - - - Tot slot wordt de MoonBlaster replayer ingeladen, die in dit - geval op adres &HC800 begint. - - - LD DE,&HC800 ; MoonBlaster replay - LD C,SETDMA - CALL BDOS - LD HL,4608 - LD DE,FCB - LD C,READ - CALL BDOS - - - Nu is de MoonBlaster replayer ingeladen en kunnen de - sampleadressen erin worden gezet en de samples kunnen naar - de MSX-AUDIO worden gekopieerd. - - - LD A,2 - OUT (&HFE),A - CALL MOVSMP - LD A,1 - OUT (&HFE),A - - LD HL,SMPBUF - LD DE,SMPADR - LD BC,56 - LDIR ; zet sampleadressen in - ; replayer - - - In dit geval had ik de hoofdroutine hier direct achter - gezet, eventueel kan die natuurlijk ook in de grote file - worden gezet. Tot slot moeten we nog even ruimte reserveren - voor de tijdelijke opslag van de sample adressen: - - - SMPBUF: DS 56 ; buffer sample adressen - - - Zoals je ziet is het laden vanuit ML dus helemaal niet - moeilijk! Nu nog even iets over ruimtebesparing. - - - C R U N C H E N - - De redactie van de Picturedisk is altijd zeer blij als de - demo's zo klein mogelijk zijn, want dan past er des te meer - op de Picturedisk. Als er met losse files wordt gewerkt kan - de redactie meestal zelf de graphics wel crunchen als dat - nog niet gedaan is, maar met een turbo loader is dat - natuurlijk onbegonnen werk. Zorg er dus altijd voor dat de - graphics worden gecruncht voordat je ze in de grote file - zet! - - - T E N S L O T T E - - Als resultaat krijg je een file WRPROMO.BIN met de loader en - een file WRPROMO.ALL met alle muziek, graphics, etc. Het - laadt niet alleen sneller maar is ook nog een stuk - overzichtelijker! Ik roep dan ook iedereen die demo's voor - de Picturedisk maakt om ze in de vorm van een turbo loader - aan te leveren! - - Stefan Boer diff --git a/sunrise_special/5/VDP Cursus 7.md b/sunrise_special/5/VDP Cursus 7.md deleted file mode 100644 index 5e937b8..0000000 --- a/sunrise_special/5/VDP Cursus 7.md +++ /dev/null @@ -1,421 +0,0 @@ - V D P C U R S U S 7 - - - - I N L E I D I N G - - In het alweer zevende deel van deze zeer populaire cursus - wordt een begin gemaakt met het behandelen van de schermmodi - van de V9938 en de opslag in het VRAM. In deel 8 volgt de - rest van dit overzicht. Als we dat achter de rug hebben, - hebben we alle theorie gehad en kunnen we beginnen met het - interessantste gedeelte: de praktijkvoorbeelden. Vele - nuttige, leerzame of gewoon leuke routines zullen de revue - passeren. - - Maar eerst moeten we nog even het laatste stukje theorie - behandelen. De MSX2+ schermen worden (helaas) erg weinig - gebruikt en ik heb ze al vele malen eerder besproken, dus - die zal ik hier buiten beschouwing laten. - - - S C H E R M M O D I - - Hoeveel schermmodi (schermsoorten) heeft een MSX2 volgens u? - Een heleboel MSX'ers zullen op deze vraag een verkeerd - antwoord geven, namelijk 9 of zelfs 8! Het juiste antwoord - is 10! Een overzicht: - - BASIC: VDP: Afkorting: - -------------------------------------------------- - SCREEN 0: WIDTH 1-40 TEXT 1 T1 - SCREEN 0: WIDTH 41-80 TEXT 2 T2 - SCREEN 3 MULTI-COLOR MC - SCREEN 1 GRAPHIC 1 G1 - SCREEN 2 GRAPHIC 2 G2 - SCREEN 4 GRAPHIC 3 G3 - SCREEN 5 GRAPHIC 4 G4 - SCREEN 6 GRAPHIC 5 G5 - SCREEN 7 GRAPHIC 6 G6 - SCREEN 8 GRAPHIC 7 G7 - --------------------------------------------------- - - Vanaf nu zal ik alle schermen benoemen volgens de afkorting - zoals die in de derde kolom staat. Per scherm zal ik nu een - overzicht geven van de mogelijkheden en hoe dat in het VRAM - is opgeslagen. Deze keer komen T1, T2 en MC aan bod. De - G-modes komen in deel 8 aan de beurt. - - - T E X T 1 - - Formaat: 24 regels van 40 kolommen tekst - Kleuren: voorgrond- en achtergrondkleur kunnen worden - gekozen uit een palet van 512 - Karakters: 256 karakters, 6 (hor) * 8 (vert) - VRAM: karakterset 2048 bytes (8 * 256) - scherminhoud 960 bytes (40 * 24) - - Voor het selecteren van de schermmode gebruikt de VDP de - bits M1-M5. Deze bits zijn te vinden in R#0 en R#1: - - -------------------------------------------------------- - 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 - -------------------------------------------------------- - - Om TEXT 1 te krijgen moet de VDP als volgt staan ingesteld: - - M1 M2 M3 M4 M5 - T1 1 0 0 0 0 - - De karakterset staat in de zogenaamde Pattern Generator - Table. Deze tabel staat in het VRAM. Elk karakter wordt - gecodeerd door 8 bytes. Er zijn 256 karakters, genummerd van - 0 t/m 255. Het beginadres van een karakter is als volgt te - berekenen: - - + 8 * karakternummer - - Bit 0 en 1 van elke byte worden niet getoond, omdat een - karakter 6 pixels breed is in plaats van 8. Het beginadres - van de Pattern Generator Table moet in R#4 staan. De 11 - laagste bits van dit adres (bit 0 t/m 10) zijn altijd 0. - Alleen de 6 bovenste bits (bit 11 t/m 16) staan in R#4: - - --------------------------------------------------------- - MSB 7 6 5 4 3 2 1 0 LSB - - R#4 0 0 A16 A15 A14 A13 A12 A11 Pattern Generator - --------------------------------------------------------- - - In BASIC is deze waarde op te vragen c.q. te veranderen - middels BASE(2). - - Voorbeeld van de opbouw van de Pattern Generator Table: - - MSB 7 6 5 4 3 2 1 0 LSB - - 0 0 1 0 0 0 0 0 + 520 - 0 1 0 1 0 0 0 0 + 521 - 1 0 0 0 1 0 0 0 + 522 - 1 0 0 0 1 0 0 0 + 523 - 1 1 1 1 1 0 0 0 + 524 - 1 0 0 0 1 0 0 0 + 525 - 1 0 0 0 1 0 0 0 + 526 - 0 0 0 0 0 0 0 0 + 527 - - De A staat op adres 65 (ASCII van A) * 8 = 520. Een 1 - betekent dat de voorgrondkleur wordt getoond, een 0 de - achtergrondkleur. - - De Pattern Name Table geeft aan welk karakter op elke - positie van het scherm wordt getoond. Het beginadres staat - in R#2. De laagste 10 bits (bit 0 t/m 9) zijn altijd 0, de - hoogste 7 bits (10 t/m 16) staan in R#2. - - ---------------------------------------------------- - MSB 7 6 5 4 3 2 1 0 LSB - - R#2 0 A16 A15 A14 A13 A12 A11 A10 Pattern Name - ---------------------------------------------------- - - In BASIC is deze waarde op te vragen c.q. te veranderen - middels BASE(0). - - De karakternummers staan in de Pattern Name Table van links - naar rechts, van boven naar onder. Dus: - - | 0 1 2 3 ... 39 - -----+----------------------------------------------- - 0 | 0 1 2 3 39 - 1 | 40 41 42 43 79 - ... | - 23 | 920 921 922 923 959 - - Het adres behorende bij de positie (X,Y) kan als volgt - worden berekend: - - + Y * 40 + X - - De schermkleuren worden gedefinieerd met R#7. De achter- - grondkleur (A, tevens de kleur van de border) wordt bepaald - door de onderste vier bits, de voorgrondkleur (V) wordt - bepaald door de bovenste vier bits. - - -------------------------------------------------- - MSB 7 6 5 4 3 2 1 0 LSB - - R#7 V3 V2 V1 V0 A3 A2 A1 A0 Text color - -------------------------------------------------- - - - T E X T 2 - - Formaat: 24 of 26.5 regels van 80 kolommen tekst - Kleuren: voorgrond- en achtergrondkleur kunnen worden - gekozen uit een palet van 512 - Karakters: 256 karakters, 6 (hor) * 8 (vert) - VRAM: karakterset 2048 bytes (8 * 256) - 24 regels: scherminhoud 1920 bytes (80 * 24) - blinktabel 240 bytes (1920 bits) - 26.5 regels: scherminhoud 2160 bytes (80 * 27) - blinktabel 270 bytes (2160 bits) - - Om TEXT 2 te krijgen moet de VDP als volgt staan ingesteld: - - M1 M2 M3 M4 M5 - T2 1 0 0 1 0 - - Bit 7 van R#9 bepaalt het aantal regels van T2. - - ------------------------------------------------- - MSB 7 6 5 4 3 2 1 0 LSB - - R#9 LN 0 S1 S0 IL EO NT DC Mode Reg #3 - ------------------------------------------------- - - Het scherm heeft 26.5 regels als LN=1. Dit wordt niet door - BASIC ondersteund. Het kan wel gebruikt worden, maar de - regels 24-26 kunnen niet met LOCATE/PRINT commando's worden - beschreven. Van de 27ste regel (regel 26) wordt alleen de - bovenste helft weergegeven. - - De Pattern Generator Table werkt hetzelfde als bij T1. Zie - dus bij T1. - - De Pattern Name Table geeft aan welk karakter op elke - positie van het scherm wordt getoond. Het beginadres staat - in R#2. De laagste 12 bits (bit 0 t/m 11) zijn altijd 0, de - hoogste 5 bits (12 t/m 16) staan in R#2. - - ---------------------------------------------------- - MSB 7 6 5 4 3 2 1 0 LSB - - R#2 0 A16 A15 A14 A13 A12 1 1 Pattern Name - ---------------------------------------------------- - - In BASIC is deze waarde op te vragen c.q. te veranderen - middels BASE(0). Let op: in R#2 zijn bit 1 en 0 altijd 1, - maar bit 11 en bit 10 van het beginadres van de Pattern Name - Table zijn toch 0! - - De karakternummers staan in de Pattern Name Table van links - naar rechts, van boven naar onder. Dus: - - | 0 1 2 3 ... 79 - -----+----------------------------------------------- - 0 | 0 1 2 3 79 - 1 | 80 81 82 83 159 - ... | - 23 | 2080 2081 2082 2083 2159 - - Het adres behorende bij de positie (X,Y) kan als volgt - worden berekend: - - + Y * 80 + X - - - B L I N K M O D E - - Aan deze mode is al eerder aandacht besteed. Elke positie op - T2 kan in de blink-mode worden gezet. Voor elke positie is - een bit gereserveerd in de blink table. Als dit bit 1 is, is - de blink mode actief. Het startadres van de blink tabel - staat in R#3 en R#10. De bovenste acht bits staan in R#3 en - R#10, de onderste negen bits zijn altijd 0. - - -------------------------------------------------------- - MSB 7 6 5 4 3 2 1 0 LSB - - R#3 A13 A12 A11 A10 A9 1 1 1 Color table low - R#10 0 0 0 0 0 A16 A15 A14 Color table high - -------------------------------------------------------- - - Let op! In R#3 zijn de bits 0 t/m 2 altijd 1, maar bit 6 t/m - 8 van het beginadres van de blink tabel zijn toch altijd 0! - - De blinkbits staan in de Blink Tabel van links naar rechts, - van boven naar onder. - - Het adres behorende bij de positie (X,Y) kan als volgt - worden berekend: - - + Y * 10 + (X\8) - - Dit blinkbits van de posities (8,4) t/m (15,4) staan dus op - adres: - - 4 * 10 + 1 = 41 - - De waarde op adres 41 wordt dan als volgt geinterpreteerd: - - 7 6 5 4 3 2 1 0 bit - (8,4) (9,4) (10,4) (11,4) (12,4) (13,4) (14,4) (15,4) - - R#7 werkt net zoals bij T1. De blinkkleuren staan in R#12, - op dezelfde manier als bij R#7. De posities waarvan het - blink-bit 1 is, zullen beurtelings in de kleuren van R#7 en - de kleuren van R#12 worden getoond. - - Het tempo waarmee dat gebeurt staat in R#13. De tijden - kunnen worden opgegeven in ca. 1/6 seconde. De bovenste vier - bits bepalen de periode waarin de kleuren van R#12 worden - getoond, de onderste vier bits bepalen de periode waarin de - kleuren van R#7 worden getoond. - - ---------------------------------------------------- - MSB 7 6 5 4 3 2 1 0 LSB - - R#12 B3 B2 B1 B0 N3 N2 N1 N0 Blink Colour - ---------------------------------------------------- - (B=blinkkleur tijd, N=normale kleur tijd) - - - M U L T I C O L O U R - - Formaat: 48 regels van 64 blokjes van 4*4 - Kleuren: 16 kleuren uit een palet van 512 - VRAM: kleuren 2048 bytes - posities 768 bytes - Sprite: Sprite mode 1 - - Om MULTI-COLOUR te krijgen moet de VDP als volgt staan - ingesteld: - - M1 M2 M3 M4 M5 - MC 0 1 0 0 0 - - De multi-colour mode zit nogal ingewikkeld in elkaar. De - multi-colour mode wordt heel weinig gebruikt, omdat de - graphics heel erg blokkerig zijn. Bovendien zit de opslag in - het VRAM zeer ingewikkeld in elkaar. Ik zal proberen om het - toch enigszins te verduidelijken. - - MC werkt met blokjes van 4*4 pixels. Deze 16 pixels hebben - allemaal dezelfde kleur. - - Een patroon bestaat in MC uit 16 blokjes, 8 hoog en 2 breed. - De patronen staan in de Pattern Generator Table. Het - beginadres is te vinden in R#4. De 11 laagste bits van dit - adres (bit 0 t/m 10) zijn altijd 0. Alleen de 6 bovenste - bits (bit 11 t/m 16) staan in R#4: - - --------------------------------------------------------- - MSB 7 6 5 4 3 2 1 0 LSB - - R#4 0 0 A16 A15 A14 A13 A12 A11 Pattern Generator - --------------------------------------------------------- - - In BASIC is deze waarde op te vragen c.q. te veranderen - middels BASE(17). - - Er zijn 256 patronen (genummerd van #0 t/m #255), die elk 8 - bytes in beslag nemen. De kleuren van de twee blokjes naast - elkaar in het patroon staan steeds in 1 byte, die van het - linkse blokje in de 4 hoogste bits en die van het rechtse - blokje in de 4 laagste bits. We stellen een patroon als - volgt voor: - - AB - CD - EF - GH - IJ - KL - MN - OP - - Elke letter staat voor een blokje. Dit patroon staat dan als - volgt in het VRAM: - - = + 8 * - - MSB 7 6 5 4 3 2 1 0 LSB - - +0 A3 A2 A1 A0 B3 B2 B1 B0 - +1 C3 C2 C1 C0 D3 D2 D1 D0 - +2 E3 E2 E1 E0 F3 F2 F1 F0 - +3 etc. - +7 O3 O2 O1 O0 P3 P2 P1 P0 - - Voor elk blokje zijn telkens vier bits gereserveerd, waarin - het kleurnummer (0-15) staat. - - Voor de Pattern Name Table verdelen wij het scherm in 768 - posities, 32 horizontaal en 24 verticaal. Verder werkt dit - weer net zo als bij de vorige modi. Het adres behorende bij - de positie (X,Y) kan als volgt worden berekend: - - + Y * 32 + X - - Het beginadres van de Pattern Name Table staat in R#2. De - laagste 10 bits (bit 0 t/m 9) zijn altijd 0, de hoogste 7 - bits (10 t/m 16) staan in R#2. - - ---------------------------------------------------- - MSB 7 6 5 4 3 2 1 0 LSB - - R#2 0 A16 A15 A14 A13 A12 A11 A10 Pattern Name - ---------------------------------------------------- - - In BASIC is deze waarde op te vragen c.q. te veranderen - middels BASE(15). - - In deze tabel staat voor elke positie welk patroon er - getoond moet worden. De Y-coordinaat van de positie bepaalt - welk gedeelte van het patroon wordt getoond. Dit gaat als - volgt: - - Y gedeelte - -------------------------------- - 00 04 08 12 16 20 ABCD - 01 05 09 13 17 21 EFGH - 02 06 10 14 18 22 IJKL - 03 07 11 15 19 23 MNOP - -------------------------------- - - Zoals u ziet is dit behoorlijk ingewikkeld. Gelukkig zal dit - scherm (zeker op een MSX2) zelden gebruikt worden. En als - het al gebruikt wordt, dan zal het vaak in BASIC zijn. En in - dat geval regelt BASIC alles voor u. - - In BASIC is de Name Table overigens zo ingevuld dat die niet - gewijzigd hoeft te worden. Daar wordt alleen de Pattern - Generator Table gewijzigd. Op de eerste 4 regels (0 t/m 3) - staan naast elkaar de patronen 0 t/m 31. Op de volgende 4 - regels de patronen 32 t/m 63, enz. Tenslotte staan op regel - 20 t/m 23 de patronen 160 t/m 191. - - De patronen 192 t/m 255 worden in BASIC dus niet gebruikt! - Dat is ook niet nodig. Rekent u even mee? 64 bij 48 blokken, - dat zijn 3072 blokken. Een patroon bevat 16 blokken, dus - 3072 / 16 = 192 patronen. - - Tot slot nog even de border kleur. Die wordt in de multi- - colour mode (en ook in alle Graphic modes) bepaald door de - vier laagste bits van R#7. De vier bovenste bits zijn niet - geldig. - - ---------------------------------------------------- - MSB 7 6 5 4 3 2 1 0 LSB - - R#7 ---ongeldig---- C3 C2 C1 C0 Border color - ---------------------------------------------------- - - De sprites zijn in het vorige deel van de VDP cursus al - behandeld. - - - T O T S L O T - - Dit was het voor deze keer. De volgende keer zullen de zeven - grafische modes worden behandeld (ja, volgens de VDP is - SCREEN 1 een grafische mode!). Experimenteert u maar eens - wat met SCREEN 3, u zult zien dat het best meevalt. - - Tot de volgende keer! - - Stefan Boer diff --git a/sunrise_special/5/VDP Cursus 8.md b/sunrise_special/5/VDP Cursus 8.md deleted file mode 100644 index 9785247..0000000 --- a/sunrise_special/5/VDP Cursus 8.md +++ /dev/null @@ -1,502 +0,0 @@ - V D P C U R S U S 8 - - - - I N L E I D I N G - - We zijn alweer bij het achtste deel van de nog immer - populaire VDP cursus aangeland. Zoals beloofd gaan we deze - keer verder met het behandelen van de opslag van schermen in - het VRAM. Deze keer zullen we SCREEN 1, 2 en 4 bekijken, - oftewel G1, G2 en G3. De laatste schermen van de V9938 (G4 - t/m G7) zullen in deel 9 worden besproken. - - Ik was eerst van plan om in dit deel alle Graphic Modes te - behandelen, maar toen ik met deze drie al over de 16 kB heen - zat heb ik besloten om het daar maar bij te laten. De - betekent dus even goed dat dit deel van de VDP cursus niet - in ��n keer kan worden ingeladen. Dat is de eerste keer in - de geschiedenis van de VDP cursus dat dat gebeurt! - - - G R A P H I C 1 - - Formaat: 24 regels van 32 kolommen tekst - Kleuren: 16 uit een palet van 512 - 2 kleuren per 8 karakters - Karakters: 256 karakters, 8 (hor) * 8 (vert) - VRAM: karakterset 2048 bytes (8 * 256) - scherminhoud 768 bytes (32 * 24) - kleuren 32 bytes - sprite patronen 2048 bytes (8 * 256) - sprite attr. 128 bytes (4 * 32) - Sprites: Sprite mode 1 - - Voor het selecteren van de schermmode gebruikt de VDP de - bits M1-M5. Deze bits zijn te vinden in R#0 en R#1: - - -------------------------------------------------------- - 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 - -------------------------------------------------------- - - Om GRAPHIC 1 te krijgen moet de VDP als volgt staan - ingesteld: - - M1 M2 M3 M4 M5 - G1 0 0 0 0 0 - - De karakterset staat in de zogenaamde Pattern Generator - Table. Deze tabel staat in het VRAM. Elk karakter wordt - gecodeerd door 8 bytes. Er zijn 256 karakters, genummerd van - 0 t/m 255. Het beginadres van een karakter is als volgt te - berekenen: - - + 8 * karakternummer - - Het beginadres van de Pattern Generator Table moet in R#4 - staan. De 11 laagste bits van dit adres (bit 0 t/m 10) zijn - altijd 0. Alleen de 6 bovenste bits (bit 11 t/m 16) staan in - R#4: - - --------------------------------------------------------- - MSB 7 6 5 4 3 2 1 0 LSB - - R#4 0 0 A16 A15 A14 A13 A12 A11 Pattern Generator - --------------------------------------------------------- - - In BASIC is deze waarde op te vragen c.q. te veranderen - middels BASE(7). - - Voorbeeld van de opbouw van de Pattern Generator Table: - - MSB 7 6 5 4 3 2 1 0 LSB - - 0 0 1 1 1 0 0 0 + 520 - 0 1 1 0 1 1 0 0 + 521 - 1 1 0 0 0 1 1 0 + 522 - 1 1 0 0 0 1 1 0 + 523 - 1 1 1 1 1 1 1 0 + 524 - 1 1 0 0 0 1 1 0 + 525 - 1 1 0 0 0 1 1 0 + 526 - 0 0 0 0 0 0 0 0 + 527 - - De A staat op adres 65 (ASCII van A) * 8 = 520. Een 1 - betekent dat de voorgrondkleur wordt getoond, een 0 de - achtergrondkleur. - - Per groep van 8 karakters kunnen de voor- en achtergrond- - kleur worden ingesteld (kar. #0-#7, #8-#15, etc). Het - startadres van de kleurentabel wordt bepaald door de waarde - van R#3 en R#10. Alleen de hoogste 11 bits (bit 6 t/m 16) - staan in deze registers: - - -------------------------------------------------------- - MSB 7 6 5 4 3 2 1 0 LSB - - R#3 A13 A12 A11 A10 A9 A8 A7 A6 Color table low - R#10 0 0 0 0 0 A16 A15 A14 Color table high - -------------------------------------------------------- - - De kleurentabel is als volgt opgebouwd: - - MSB 7 6 5 4 3 2 1 0 LSB - - ---V--- ---A--- + 0 karakters 0-7 - ---V--- ---A--- + 1 karakters 8-15 - - ---V--- ---A--- + 31 karakters 248-255 - - Waarbij V staat voor de voorgrondkleur (0-15) en A voor de - achtergrondkleur (ook 0-15). - - De Pattern Name Table geeft aan welk karakter op elke - positie van het scherm wordt getoond. Het beginadres staat - in R#2. De laagste 10 bits (bit 0 t/m 9) zijn altijd 0, de - hoogste 7 bits (10 t/m 16) staan in R#2. - - ---------------------------------------------------- - MSB 7 6 5 4 3 2 1 0 LSB - - R#2 0 A16 A15 A14 A13 A12 A11 A10 Pattern Name - ---------------------------------------------------- - - In BASIC is deze waarde op te vragen c.q. te veranderen - middels BASE(5). - - De karakternummers staan in de Pattern Name Table van links - naar rechts, van boven naar onder. Dus: - - | 0 1 2 3 ... 31 - -----+----------------------------------------------- - 0 | 0 1 2 3 31 - 1 | 32 33 34 35 63 - ... | - 23 | 736 737 738 739 767 - - Het adres behorende bij de positie (X,Y) kan als volgt - worden berekend: - - + Y * 32 + X - - De borderkleur wordt gedefinieerd met R#7, en wel door de - vier minst significante bits. - - ---------------------------------------------------- - MSB 7 6 5 4 3 2 1 0 LSB - - R#7 --ongeldig--- B3 B2 B1 B0 Border color - ---------------------------------------------------- - - Het tweede gedeelte, met G2 en G3, kunt u in het submenu - vinden. - - Stefan Boer - - - - - TWEEDE GEDEELTE - - - V D P C U R S U S 8 - - - - G R A P H I C 2 E N 3 - - Deze schermmodes (SCREEN 2 en 4) komen zoveel overeen, dat - ik ze hier in ��n keer bespreek. - - Formaat: 24 regels van 32 patronen - Kleuren: per 8 pixels 2 van de 16 kleuren - deze 16 kleuren uit een palet van 512 - Patronen: 3*256 patronen, 8 (hor) * 8 (vert) - VRAM: patronen 6144 bytes (8 * 3 * 256) - kleuren 6144 bytes (8 * 3 * 256) - scherminhoud 768 bytes (24 * 32) - spritepatronen 2048 bytes (8 * 256) - sprite attr. 128 bytes (32 * 4) - Sprites: G2: Sprite Mode 1 - G3: Sprite Mode 2 - - Graphic 2 komt overeen met SCREEN 2, Graphic 3 komt overeen - met SCREEN 4. De enige twee verschillen tussen G2 en G3 - zijn: - - - G2 is wel MSX1 compatibel, G3 niet - - G2 heeft Sprite Mode 1, G3 heeft Sprite Mode 2 - - Aan het einde van het artikel zullen ook heel kort de beide - Sprite Modes en de verschillen worden behandeld. - - Om G2 resp. G3 te krijgen moet de VDP als volgt staan - ingesteld: - - M1 M2 M3 M4 M5 - G2 0 0 1 0 0 - G3 0 0 0 1 0 - - SCREEN 2 en 4 hebben drie pattern generators, deze pattern - generators werken net zo als de pattern generator van SCREEN - 1. Het scherm is verdeeld in drie gelijke delen van 8 regels - hoog: - - Regel 0 t/m 7: Pattern generator #1 - Regel 8 t/m 15: Pattern generator #2 - Regel 16 t/m 23: Pattern generator #3 - - Voor elke positie op het scherm (er zijn 768 posities) kan - dus een apart pattern worden gedefinieerd, omdat elke - pattern generator 256 patterns bevat. Een pattern uit - pattern generator #2 kan niet op regel 7 worden getoond! Op - deze manier wordt er een 256 bij 192 pixel scherm - gesimuleerd, terwijl er in feite toch met patterns - (karakters) wordt gewerkt. - - Het startadres van de pattern generator tables staan in R#4, - alleen de 4 hoogste bits (13 t/m 16) kunnen worden - opgegeven. Het startadres van de generator tables is dus - altijd een veelvoud van 8 kB. - - --------------------------------------------------------- - MSB 7 6 5 4 3 2 1 0 LSB - - R#4 0 0 A16 A15 A14 A13 1 1 Pattern Generator - --------------------------------------------------------- - - Hoewel bit 1 en 0 van R#4 in G2 en G3 altijd op "1" staan, - moet hiervoor toch 0 worden gelezen! In BASIC kan deze - waarde worden opgevraagd c.q. veranderd middeld BASE(12) in - SCREEN 2 of BASE(22) in SCREEN 4. - - Deze pattern generator tables zijn als volgt opgebouwd. Voor - elk patroon zijn acht bytes gereserveerd. Elke bit in die - byte stelt een pixel voor. Een 1 betekent dat dat pixel in - de voorgrondkleur wordt getoond, een 0 de achtergrondkleur. - - Op het adres dat in R#4 staat begint generator #1. Voor elk - pattern zijn 8 bytes gereserveerd. Er zijn 8 patronen, - genummerd van #0 t/m #255, dus de tabel is 2048 bytes lang. - Daarachter volgende generator #2 en #3 op dezelfde manier. - Een aantal voorbeelden (adres ten opzichte van waarde in - R#4): - - Adres: Bevat: - - 0 Regel 0 van pattern #0, generator #1 - 1 Regel 1 van pattern #0, generator #1 - 7 Regel 7 van pattern #0, generator #1 - 8 Regel 0 van pattern #1, generator #1 - 2047 Regel 7 van pattern #255, generator #1 - 2048 Regel 0 van pattern #0, generator #2 - 4095 Regel 7 van pattern #255, generator #2 - 5572 Regel 4 van pattern #184, generator #3 - 6143 Regel 7 van pattern #255, generator #3 - - Het beginadres van een bepaald pattern kan dus als volgt - worden berekend: - - adres = (generator-1)*2048 + pattern*8 - - - De kleurentabel werkt net zo, alleen wordt nu per regel van - een pattern aangegeven welke kleur de voorgrondkleur is en - welke kleur de achtergrondkleur. Hiervoor zijn dus ook 8 - bytes per pattern nodig. Er zijn ook drie kleurentabellen. - De kleurentabellen beginnen op het adres dat in R#3 en R#10 - wordt bepaald: - - -------------------------------------------------------- - MSB 7 6 5 4 3 2 1 0 LSB - - R#3 A13 1 1 1 1 1 1 1 Color table low - R#10 0 0 0 0 0 A16 A15 A14 Color table high - -------------------------------------------------------- - - Merk op dat alleen de vier hoogste bits kunnen worden - veranderd (bit 13 t/m 16). De bits 0 t/m 6 van R#3 zijn - altijd "1", toch moet daar voor worden gelezen! Ook deze - tabel begint dus altijd op een veelvoud van 8 kB. - - De kleurentabel is als volgt opgebouwd: - - MSB 7 6 5 4 3 2 1 0 LSB - - ---V--- ---A--- + 0 tabel 1 karakter 0 regel 0 - ---V--- ---A--- + 1 regel 1 - ---V--- ---A--- + 7 regel 7 - - ---V--- ---A--- + 6143 tabel 3 karakter 255 regel 7 - - Waarbij V voor de voorgrondkleur staat en A voor de achter- - grondkleur. Het beginadres van de kleuren van een pattern - kan als volgt worden gevonden: (tabel=1, 2 of 3) - - adres = (tabel-1)*2048 + pattern*8 - - De Pattern Name Table geeft aan welk karakter op elke - positie van het scherm wordt getoond. Het scherm is hierbij - verdeeld in drie blokken: upper, middle en lower. U raadt - het al: voor de posities in het upper gedeelte (regel 0 t/m - 7) wordt pattern generator #1 en color table #1 gebruikt, en - voor middle en lower #2 resp. #3. Op deze manier kan voor - elk van de 768 posities een ander pattern en andere kleuren - worden gekozen, waardoor een 256 bij 192 pixelscherm wordt - gesimuleerd. - - Het beginadres van de pattern name tabel staat in R#2. De - laagste 10 bits (bit 0 t/m 9) zijn altijd 0, de hoogste 7 - bits (10 t/m 16) staan in R#2. - - ---------------------------------------------------- - MSB 7 6 5 4 3 2 1 0 LSB - - R#2 0 A16 A15 A14 A13 A12 A11 A10 Pattern Name - ---------------------------------------------------- - - In BASIC is deze waarde op te vragen c.q. te veranderen - middels BASE(10) in SCREEN 2, en BASE(20) in SCREEN 4. - - De karakternummers staan in de Pattern Name Table van links - naar rechts, van boven naar onder. Dus: - - | 0 1 2 3 ... 31 - -----+----------------------------------------------- - 0 | 0 1 2 3 31 - 1 | 32 33 34 35 63 - ... | - 23 | 736 737 738 739 767 - - Het adres behorende bij de positie (X,Y) kan als volgt - worden berekend: - - + Y * 32 + X - - Nogmaals de tabel met de blokken: - - Naam: Regels: Pattrn: Color: - ------------------------------ - Upper 0-7 #1 #1 - Middle 8-15 #1 #1 - Lower 16-23 #1 #1 - ------------------------------ - - Let u hier goed op, patroon #13 is een heel ander patroon op - regel 7 dan op regel 8! - - De borderkleur wordt gedefinieerd met R#7, en wel door de - vier minst significante bits. - - ---------------------------------------------------- - MSB 7 6 5 4 3 2 1 0 LSB - - R#7 --ongeldig--- B3 B2 B1 B0 Border color - ---------------------------------------------------- - - - S C R E E N 4 V E E L G E B R U I K T - - Deze schermen zijn niet bitmapped (zoals de SCREENs 5 t/m - 8). Ze zijn daarom niet zo makkelijk te programmeren, om de - kleur van een bepaald pixel te veranderen moet er op drie - plaatsen in het VRAM iets worden veranderd, en bovendien - gaan er dan soms andere pixels in de buurt mee. Er kunnen - maar twee kleuren per acht horizontale pixels worden - gebruikt, dat komt de kwaliteit van de graphics ook niet ten - goede. De commando's van de VDP kunnen niet worden gebruikt - om te kopi�ren. - - Toch wordt SCREEN 4 behoorlijk vaak gebruikt bij MSX2 - software. Om maar eens een paar bekende titels te noemen: - Hydefos, Psycho World, Space Manbow (!!), Firehawk en - Superrunner. Misschien gelooft u het eerst niet (net als - ik), maar als u goed kijkt kunt u zien dat deze spellen - nergens meer dan twee kleuren per acht pixels gebruiken in - het speelscherm (vaak is het gedeelte met de score e.d. wel - in SCREEN 5, d.m.v. een screensplit). - - SCREEN 4 is op de sprites na gelijk aan SCREEN 2 op MSX1. - Waarom zijn bovengenoemde spellen dan niet voor MSX1 - gemaakt? De eerste reden noemde ik al: de sprites. In Sprite - Mode 2 mogen twee maal zoveel sprites op een horizontale - regel worden geplaatst, dus dat knippert een stuk minder. - Maar dat is niet de enige reden: door gebruik te maken van - de verticale hardwarescroll en het adjustregister van de - MSX2 kunnen op deze computer smooth scrolls in alle - richtingen worden gemaakt. Dat kan op MSX1 niet. - - In SCREEN 5 (veel meer een echt MSX2 scherm) kan dat veel - minder goed, omdat daar veel meer VRAM moet worden - verplaatst om te scrollen. En dat is nu precies het grote - voordeel van SCREEN 4 ten opzichte van SCREEN 5: SCREEN 4 - gebruikt minder VRAM en animaties nemen dus minder tijd in - beslag! - - - S P R I T E M O D E 1 E N 2 - - Nog even de verschillen tussen Sprite Mode 1 en Sprite Mode - 2. Eerst even een overzicht in welke schermen ze kunnen - worden gebruikt: - - Scherm: Sprite Mode: - ---------------------------- - T1 niet - T2 niet - MC 1 - G1 1 - G2 1 - G3 2 - G4 2 - G5 2 - G6 2 - G7 2 - ---------------------------- - - Kort overzicht van de verschillen: - - Sprite Mode 1: Sprite Mode 2: - ------------------------------------------------------------ - Kleuren 1 kleur per sprite 1 kleur per lijn - van een sprite - Aantal op ��n - horizontale 4 8 - lijn - - Sprite 32 pixels - naar links mogelijk mogelijk - verplaatsen per lijn - - Overlappende niet mogelijk mogelijk - sprites OR - (per lijn) - - Botsing detectie - uitzetten (per niet mogelijk mogelijk - lijn) - ------------------------------------------------------------ - - In deel zes van de VDP cursus wordt Sprite Mode 2 uitgebreid - besproken. Voor Sprite Mode 1 is er geen kleurentabel, - verder werken de tabellen hetzelfde. Behalve de attribuut- - tabel, daar wordt de byte die bij Sprite Mode 2 niet wordt - gebruikt, gebruikt voor de kleur van de sprite: - - Attributen per sprite: - - +0 Y coordinaat - +1 X coordinaat - +2 Patroon nummer - +3 Kleurcode (0-15) - - Indien bit 7 van de kleurcode wordt gezet, wordt de sprite - 32 pixels naar links verplaatst. Helaas weten veel - programmeurs niet wat hier het nut van is. Ik zal dat dus - maar eens uitleggen. - - - H E T N U T V A N E C - - Bit 7 van de kleurcode heet bij de beide Sprite Modes "EC". - Wat heeft het nu voor nut om een (gedeelte van een) sprite - 32 pixels naar links te verplaatsen? - - U kunt dit gebruiken om sprites ook aan de linkerkant van - het scherm pixel voor pixel te laten verdwijnen c.q. - verschijnen. Bij van links naar rechts bewegende sprites - zien we vaak dat de sprite aan de rechterkant netjes - verdwijnt, maar aan de linkerkant zomaar opeens helemaal op - het scherm staat. - - Dit komt omdat X-coordinaat 255 betekent dat alleen de meest - linkse pixels van de sprite nog uiterst rechts te zien zien, - en bij X=0 staat de sprite in zijn geheel strak tegen de - linkerkant van het scherm. - - U kunt dit voorkomen door op de juiste manier gebruik te - maken van het EC bit, dat dus ook op MSX1 al aanwezig was! - Stel u wilt een sprite van rechts naar links laten gaan, - terwijl de sprite aan beide kanten van het scherm pixel voor - pixel verschijnt c.q. verdwijnt. Dit gaat als volgt: - - 1) Zet EC op 0 - 2) Verander de X coordinaat van 255 naar 0 - 3) Zet EC op 1 en de X coordinaat gelijktijdig op 32 - 4) Verander de X coordinaat van 32 naar 0 - - Het is heel belangrijk dat stap 3 heel snel gebeurt, want - anders zal er een knippering in de animatie optreden. - - Ik hoop dat veel programmeurs dit nu ook gaan gebruiken, - want het is in sommige demo's en spellen echt geen gezicht! - - - T O T D E V O L G E N D E K E E R - - Hiermee sluit ik dit achtste deel af. De volgende keer - worden SCREEN 5 t/m 8 behandeld, oftewel Graphic 4 t/m 7. - Daarna kunnen we eindelijk beginnen met de praktijk- - voorbeelden, met zeer veel machinetaalroutines. - - Stefan Boer diff --git a/sunrise_special/5/VDP Cursus 9.md b/sunrise_special/5/VDP Cursus 9.md deleted file mode 100644 index 637643f..0000000 --- a/sunrise_special/5/VDP Cursus 9.md +++ /dev/null @@ -1,187 +0,0 @@ - V D P C U R S U S 9 - - - Zoals beloofd deze keer de opslag van SCREEN 5 t/m 8 in het - VRAM, of liever gezegd de Graphic modes 4 t/m 7. Dit zijn - allen zgn. bitmap schermen, en de opslag in het VRAM gaat - dan ook bij allemaal volgens hetzelfde principe. - - - B I T M A P - - Bij het bitmap systeem wordt de kleur van ieder pixel - bepaald door een bepaald aantal bits. Deze bits worden - alleen voor dit pixel gebruikt, waardoor geen "color spill" - effecten optreden, zoals bij SCREEN 2 en 4 of de MSX2+ - schermen 10 t/m 12. - - Het aantal kleuren dat tegelijkertijd op het scherm kan - worden getoond is hierbij uiteraard afhankelijk van het - aantal bits dat per pixel beschikbaar is. Een overzichtje: - - SCREEN 5 G4 4 bits/pixel 16 kleuren - SCREEN 6 G5 2 bits/pixel 4 kleuren - SCREEN 7 G6 4 bits/pixel 16 kleuren - SCREEN 8 G7 8 bits/pixel 256 kleuren - - Deze bits worden zoveel mogelijk in een byte gepropt. Omdat - een byte zoals u ongetwijfeld weet uit 8 bits bestaat - betekent dat in G4 en G6 de kleuren van twee pixels in een - byte worden opgeslagen, bij G5 zijn dat er 4 en bij G7 - slechts 1. Hierbij is het zo dat de kleur van het meest - linkse pixel ook altijd in de meest linkse bits is - opgeslagen. Samengevat levert dit onderstaand schema op: - - MSB 7 6 5 4 3 2 1 0 LSB - G4 en G6 ------1------ ------2------ - G5 --1-- --2-- --3-- --4-- - G7 --------------1-------------- - - - V O L G O R D E - - We weten nu dus hoe de kleurinformatie over de bytes van het - VRAM verdeeld is, maar we weten nog niet in welke volgorde - die bytes staan, of waar we dus de kleurinformatie van een - bepaald pixel kunnen vinden. - - Deze informatie over de pixels wordt per lijn opgeslagen. De - eerste lijn van het scherm bestaat uit de pixels (0,0), - (1,0), (2,0), .... tot (255,0) op G4 en G7 resp. (511,0) op - G5 en G6. De kleuren staan van links naar rechts in het - VRAM. Als het beeldscherm uit slechts ��n lijn zou bestaan - zou dus de volgende formule gelden: - - = \ - - (Let op: er staat een "\" (integerdeling) en niet een "/" - (normale deling)!) De kleuren van de pixels (0,0) en (1,0) - staan op SCREEN 5 en 7 dus samen in byte 0, die er als volgt - uit ziet: - - MSB 7 6 5 4 3 2 1 0 LSB - ----(0,0)---- ----(1,0)---- - - Door een VPOKE 0,&HF1 wordt pixel (0,0) dus wit en pixel - (1,0) zwart. De kleur van het pixel (255,0) staat bij SCREEN - 8 in byte nummer 255, en neemt het hele byte in beslag. - - Natuurlijk bestaat het scherm niet uit slechts ��n lijn, - maar uit 212 lijnen (genummerd van 0 t/m 211). De informatie - van lijn 1 staat direct achter die van lijn 0, en daarachter - weer lijn 2, enz. We kunnen dus zeggen dat de informatie van - linksboven naar rechtsonder in het VRAM is opgeslagen. We - breiden de formule dus nog wat uit: - - = \ + - * - - Hierbij is de volgende tabel misschien handig: - - Aantal pixels per byte: Aantal bytes per lijn: - ------------------------------------------------------ - G4 2 128 - G5 4 128 - G6 2 256 - G7 1 256 - ------------------------------------------------------ - - - P A L L E T - - De modes 4 t/m 6 werken met een palet. Bij G4 en G6 bestaat - dit palet uit 16 kleuren, bij G5 uit 4. Het kleurnummer dat - in de databytes wordt opgeslagen correspondeert met het - paletnummer. - - Bij G7 (SCREEN 8) gaat het heel anders. Het kleurnummer is - hier als volgt opgebouwd: - - MSB 7 6 5 4 3 2 1 0 LSB - ----G---- ----R---- --B-- - - Hierbij staat G voor de groene intensiteit (0-7), R voor de - rode intensiteit (0-7) en B voor de blauwe intensiteit - (0-7). Er is hier dus geen sprake van een palet, de kleuren - staan vast. - - Het palet wordt bij SCREEN 5 t/m 7 door BASIC in het VRAM - gezet. Bij SCREEN 5 en 6 is dit &H7680, en bij SCREEN 7 - &HFA80. Het veranderen van deze waardes door VPOKE heeft pas - effect na een COLOR=RESTORE. In machinetaal wordt het palet - normaal gesproken gewoon veranderd door naar Port #2 te - schrijven (OUT poort &H9A). Hiervoor verwijs ik u naar deel - 1 van de VDP cursus. - - - G E H E U G E N G E B R U I K - - Zoals u weet hebben G4 en G5 4 pages, en G6 en G7 2. Deze - pages staan als volgt in het VRAM: - - 00000H page 0 G4/G5 page 0 G6/G7 - ------------ - 08000H page 1 G4/G5 - ------------ ------------ - 10000H page 2 G4/G5 page 1 G6/G7 - ------------ - 18000H page 3 G4/G5 ------------ - - Voor de VDP is een scherm 256 lijnen hoog, en er per page - dan ook 32 kB (G4/G5) respectievelijk 64 kB (G6/G7) in - beslag worden genomen. Van deze 256 lijnen worden er slechts - 212 (of 192) op het scherm getoond. Welke, dat wordt bepaald - door de waarde in R#23 (beter bekend als VDP(24)). - - Omdat de lijnen vanaf 212 normaal gesproken niet te zien - zijn, worden deze gebruikt om de spritedata in op te slaan. - Hiervoor verwijs ik u naar het deel van de VDP cursus dat - aan sprites was gewijd. SCREEN 5 t/m 8 hebben Sprite Mode 2. - - Bij het wegsaven van schermen met BSAVE kunt u de volgende - eindadressen gebruiken: - - SCREEN: met palet: zonder palet: - --------------------------------------------- - 5 &H769F 27135 - 6 &H7687 27135 - 7 &HFA9F 54271 - 8 nvt 54271 - --------------------------------------------- - - - S C R E E N S E L E C T E R E N - - Tot slot nog even de juiste bits om de schermen te - selecteren. U vindt deze bits in R#0 en R#1, waarvan ik dus - eerst maar even de indeling geef: - - MSB 7 6 5 4 3 2 1 0 LSB - R#0 0 DG IE2 IE1 M5 M4 M3 0 Mode Reg #0 - R#1 0 BL IE0 M1 M2 0 SI MAG Mode Reg #1 - - Het gaat om de bits M1 t/m M5. Bij de in dit artikel - besproken grafische schermen horen de volgende waardes van - M1 t/m M5: - - M1 M2 M3 M4 M5 - ------------------------------------------ - G4 0 0 1 1 0 - G5 0 0 0 0 1 - G6 0 0 1 0 1 - G7 0 0 1 1 1 - ----------------------------------------- - - - T O T S L O T - - Hiermee is een eind gekomen aan het zeer lange overzicht van - alle theorie betreffende de Video Display Processor in uw - MSX computer. Dit betekent niet dat de cursus nu stopt, in - tegendeel. Vanaf het volgende deel zullen we toepassingen - gaan behandelen. Het geleerde zal dan eindelijk in - machinetaal worden toegepast. - - Tot de volgende keer! - - Stefan Boer diff --git a/sunrise_special/5/Werken met ASCII C deel 3.md b/sunrise_special/5/Werken met ASCII C deel 3.md deleted file mode 100644 index 9b92b23..0000000 --- a/sunrise_special/5/Werken met ASCII C deel 3.md +++ /dev/null @@ -1,293 +0,0 @@ - H E T W E R K E N M E T A S C I I C - - D E E L 3 - - - H E T G E N E R E R E N V A N S N E L L E - - C O D E M E T A S C I I M S X C - - - Zoals ook al in deel 1 van deze serie staat vermeld, - genereert de code optimizer van ASCII MSX C vrij snelle - code. Er kan echter met deze compiler in verschillende modi - gewerkt worden die allemaal hun eigen invloed hebben op de - snelheid van de gegenereerde code. - - In dit deel van de cursur zullen achtereenvolgens de - volgende onderwerpen worden besproken: - - 1) De compiler directives 'nonrec' en 'recursive' - 2) De compiler directives 'noregalo' en 'regalo' - 3) Algemene wenken voor het maken van snelle code - 4) De werking van XESCO - 5) Het gebruik van XESCO - 6) Aanwijzingen m.b.t. de source van XESCO - - [Nvdr. Omdat XelaSoft's Code Optimizer een beetje lang is, - heb ik de afkorting XESCO verzonnen.] - - - 1 ) D E C O M P I L E R D I R E C T I V E S - - N O N R E C E N R E C U R S I V E - - Normaal gaat de compiler ervan uit dat alle functies - recursief zijn. Daarom wordt de code zo aangemaakt dat een - functie alle locale variabelen op de stack bijhoudt. Dit is - echter niet bevordelijk voor de snelheid. Aangezien ook - ASCII dit heeft ingezien, hebben ze hier een oplossing voor - verzonnen: Als je weet dat een bepaalde functie niet - recursief is dan kun je dit aan de compiler vertellen met de - compiler directive 'nonrec'. - - V O O R B E E L D - - Stel je hebt de volgende functie die de som van een lijst - getallen berekent - - int sum(lijst, aantal) - int *lijst; - int aantal; - { - int sum; - - while (aantal--) - sum += *(lijst++); - return sum; - } - - Deze functie is niet recursief (ze roept zichzelf namelijk - nergens aan, ook niet via een omweg). - - Om dit aan de C compiler door te geven dient de header van - de functie vervangen te worden door: - - nonrec int sum(lijst, aantal) - - - Als je wilt hebben dat de compiler vanaf een bepaald punt in - de source voor alle functies niet recursieve code genereert, - dan kan dit met een compiler directive, namelijk: - - #pragma nonrec /* alle functies vanaf - hier zijn niet recursief */ - - En dit kan weer worden uitgezet met: - - #pragma recursive /* alle functies vanaf - hier zijn recursief */ - - - 2 ) D E C O M P I L E R D I R E C T I V E S - - N O R E G A L O E N R E G A L O - - De compiler van ASCII doet normaal aan - register-optimalisatie, dit houdt in dat locale variabelen - zoveel mogelijk in de registers worden bijgehouden. Pas als - dit niet kan (er zijn bijv. teveel variabelen tegelijk in - gebruik), dan worden sommige variabelen in het geheugen - bijgehouden. Dit laatste kan dus op twee manieren gebeuren, - namelijk op de stapel (bij recursieve procedures) of via - directe adressering in het 'normale' geheugen (bij niet - recursieve procedures). - - Soms kan de register-optimalisatie misgaan, in dit geval kan - de register-optimalisatie worden uitgezet met: - - #pragma noregalo /* vanaf hier wordt geen register- - optimalisatie gebruikt */ - - Het weer aanzetten kan vervolgens met: - - #pragma regalo /* vanaf hier wordt wel register- - optimalisatie gebruikt */ - - Een voorbeeld waarin de register-optimalisatie misgaat (uit - de C handleiding). - - int n; - int *p; - - p = &n; - n = 10; - *p = 100; - printf("%d", n); - - In dit geval zijn er slechts 2 variabelen, namelijk n en p. - Deze kunnen dus in registers worden bijgehouden. De compiler - zal de waarde 10 dan ook in het register zetten waarin n - wordt bijgehouden en dit register vervolgens doorgeven bij - de printf instructie. Het feit dat de echte waarde van n dan - via de pointer p is veranderd ziet de compiler niet. Dit zou - wel goed gaan als de code er als volgt uit had gezien: - - int n; - int *p; - - n = 10; - p = &n; /* nu zijn n = 10 en p = &n verwisseld */ - *p = 100; - printf("%d",n); - - De compiler zal nu namelijk de waarde van n in het geheugen - opslaan voordat in de pointer p het adres van de variabele n - wordt gestopt, en bij de printf zal de waarde van deze n - weer worden opgehaald. - - Bij de register-optimalisatie kijkt de compiler naar het - totale variabelen gebruik binnen een functie. In het - algemeen is het zo dat als er binnen een lus maar weinig - variabelen worden gebruikt, dat dan de variabelen binnen die - lus in registers worden bijgehouden. Buiten de lus kan de - register-optimalisatie weer anders zijn. - - Verder is het zo dat de compiler bij korte functies vaak - beter herkent wat in registers kan dan bij grote, complexe - functies. Het is daarom verstandig om een grote functie - zoveel mogelijk op te splitsen in kleinere functies die dan - worden aangeroepen vanuit die grote functie (vanuit het - standpunt van gestructureerd programmeren bekeken is dit - toch al aan te bevelen!). - - - 3 ) A L G E M E N E W E N K E N V O O R - - H E T M A K E N V A N S N E L L E C O D E - - Kort samengevat is de algemene werkwijze voor het maken van - snelle code als volgt: - - - Geef aan welke functies niet recursief zijn zodat de - compiler bij deze functies de variabelen niet op de stack - hoeft bij te houden. - - - Laat de register-optimalisatie zoveel mogelijk aanstaan. - Mocht de register-optimalisatie in een zeldzaam geval - misgaan, kijk dan of je de code kunt herschrijven. Gebruik - de '#pragma noregalo' directive pas als het niet anders - kan. - - - Maak liever veel kleine functies dan een paar grote. Let - er bij de opsplitsing in kleine functies wel op, dat je - geen extra complexiteit introduceert doordat je een - ingewikkeld algoritme te ver probeert op te splitsen! - - - 4 ) D E W E R K I N G V A N X E S C O - - Als bovenstaande werkwijze wordt gevolgd, kan er behoorlijk - snelle code worden verkregen. Het kan echter nog sneller. - Zoals namelijk ook al in deel 1 stond, maakt de code - generator alleen gebruik van instructies die de Intel 8080 - kent. Hierdoor worden sommige dingen een beetje dom - aangepakt (vanuit Z80 standpunt bekeken), een voorbeeld - hiervan is het volgende stuk code: - - push hl - ld hl,(variable) - ld c,l - ld b,h - pop hl - - Dit kan op de Z80 natuurlijk een stuk eenvoudiger, op de Z80 - kan het namelijk als volgt: - - ld bc,(variable) - - Om dit soort stukken Intel 8080 code te vervangen door - equivalente Z80 instructies heb ik een code optimizer - geschreven. Deze optimizer kan tussen de code generatie en - de assemblatie in komen. De C batch file kan er dan - bijvoorbeeld als volgt komen uit te zien: - - (Staat op disk als C.BAT.) - - cf %1 - cg -k %1 - optimize %1.mac %1.opt - del %1.mac - ren %1.opt %1.mac - m80 =%1 - del %1.mac - l80 ck,%1,clib/s,crun/s,cend,%1/n/e:xmain - - XESCO kan de meeste 8080 LD instructie-groepen vervangen - door de juiste Z80 LD instructie. Verder worden de shift - instructies iets effici�nter opgelost. Normaal maakt de - compiler voor iedere shift instructie een CALL naar een - systeemroutine (uit CRUN.REL). De routines die hier staan - zijn dan ook nog op zo'n algemene manier geschreven dat - zelfs een >>0 of <<0 goed wordt uitgevoerd. Dit introduceert - echter extra overhead (namelijk de CALL en de RET instructie - en de controle op een 0-count). Daarom vervangt de code - optimizer een call naar een shift instructie door een stukje - code dat deze shift instructie uitvoert. Hierbij kan de - optimizer 2 verschillende stukken code aanmaken: - - - Code die wel controleert op een 0-count (het standaard - geval) - - - Code die niet controleert op een 0-count. Om dit 2de geval - te krijgen dien je de optie /z op te geven. Doe dit alleen - als je zeker weet dat er geen shift over een afstand van 0 - bits kan voorkomen! - - Verder is het zo dat de code optimizer ook nog controleert - of je een shift over een constante afstand doet. Als je - namelijk over een afstand van 1 of van 2 schuift (dus >>1, - >>2, <<1 of <<2), dan wordt er geen lus gemaakt om de shift - instructie uit te voeren, maar er worden een paar register - shift instructies achter elkaar gezet. - - Behalve deze Z80-optimalisaties kent XESCO ook nog twee - R800-optimalisaties. Deze kunnen worden geactiveerd met de - optie /R. Als deze optie is opgegeven worden namelijk alle - calls naar de multiply routines vervangen door R800 multiply - instructies. In dit geval is de code uiteraard wel alleen - nog maar geschikt voor de MSX turbo R. - - - 5 ) H E T G E B R U I K V A N X E S C O - - Het gebruik van de code optimizer is als volgt: - OPTIMIZE sourcefile destinationfile [optionele parameters] - - Hiermee wordt het bestand 'sourcefile' ingelezen, en de - geoptimaliseerde code wordt weggezet in het bestand - 'destinationfile'. - - De optionele parameters zijn: - /Z: controleer niet op een 0-count bij de shift instructies - /R: gebruik de multiply instructie op de R800 - - Op deze disk staan 2 versies van de code optimizer, - namelijk: - - OPTD1.COM: de optimizer gecompileerd met MSX C 1.1, voor - onder MSX-DOS 1. - OPTD2.COM: de optimizer gecompileerd met MSX C 1.2, voor - onder MSX-DOS 2 - - - 6 ) A A N W I J Z I N G E N M . B . T . D E - - S O U R C E V A N X E S C O - - Behalve de gecompileerde versies, staat ook de source van de - optimizer op de disk, deze source bestaat uit 2 bestanden: - OPTIMIZE.C: de source van de optimizer - PCMSX.H : een headerfile om de optimizer zowel op de PC - als op de MSX te kunnen compileren. - - Deze source is public domain, ze dient ter studie ende - vermaak en mag NIET gewijzigd worden verspreid (veranderen - voor eigen gebruik mag, maar verspreid de veranderde source - en de object code die erbij hoort niet!). Laat het me weten - als je nog interessante idee�n hebt voor toekomstige versies - van XESCO zodat ze verwerkt kunnen worden. Ik ben bereikbaar - op onderstaand adres of via email op het adres: - wulms@stpc.leidenuniv.nl - - Alex Wulms diff --git a/sunrise_special/6/Bepalen van nulpunten.md b/sunrise_special/6/Bepalen van nulpunten.md deleted file mode 100644 index fdb2c3b..0000000 --- a/sunrise_special/6/Bepalen van nulpunten.md +++ /dev/null @@ -1,209 +0,0 @@ - B E P A L E N V A N N U L P U N T E N - - - In de serie numerieke wiskunde op de Special is deze keer - het bepalen van een nulpunt van een niet-lineaire functie - aan de beurt (de methodes kunnen uiteraard ook voor lineaire - functies worden gebruikt, maar dat is onzinnig omdat de - oplossing daarvan gewoon kan worden uitgerekend). - - f(x) is een functie van R naar R en we zijn op zoek naar een - x waarvoor geldt f(x) = 0. Er kunnen uiteraard meerdere - nulpunten zijn, de hier besproken algoritmes geven echter - slechts ��n nulpunt. Indien je alle nulpunten wilt vinden - moet het algoritme dus meerdere keren worden aangeroepen met - een ander startinterval. We gaan er van uit dat f een - continue functie is. - - - B I S E C T I E - - Het meest voor de hand liggende algoritme om dit probleem - aan te pakken is bisectie. Deze methode is gebaseerd op de - tussenwaardestelling: - - Zij J een interval, en f: J --> R een continue functie. Neem - x1 en y1 uit J, zo dat x1 < y1, zij c een waarde tussen - f(x1) en f(y1). Dan bestaat er een t zo dat x1 <= t <= y1 en - f(t)=c. - - Het bewijs laat ik hier achterwege, voor het bewijs wordt - overigens een techniek gebruikt die sterk lijkt op bisectie! - Het komt erop neer dat als bijvoorbeeld f(1)=3 en f(2)=5, en - f(x) is continu, dat f(x) dan ergens tussen 1 en 2 de waarde - 4 aan moet nemen. - - Je begint met een gesloten interval [a,b] waarvoor geldt - f(a)f(b) < 0. Volgens de tussenwaardestelling ligt er dan - minstens ��n nulpunt in [a,b]. De tekens van f(a) en f(b) - zijn immers verschillend als f(a)f(b) < 0. - - Vervolgens bereken je c als het midden van het interval, dus - c := (a+b)/2. Nu zijn er drie gevallen te onderscheiden: - - f(a)f(c) < 0: het nulpunt ligt in [a,c] - f(a)f(c) > 0: het nulpunt ligt in [c,b] - f(a)f(c) = 0: c is het nulpunt - - In de eerste twee gevallen neem je [a,c] respectievelijk als - het nieuwe interval en ga je weer verder, anders ben je - klaar. Aangezien de computer niet met oneinige precisie - werkt kan het optreden dat dat nooit voorkomt, daarom is het - nodig om een stopcriterium in te bouwen, we be�indigen het - algoritme ook als de lengte van het interval kleiner is dan - een bepaalde tolerantie (een heel klein getal, bijvoorbeeld - 0.000000000001). - - Ik heb dit algoritme geprogrammeerd in het onderstaande - BASIC programma dat ook op de disk te vinden is. Probeer het - eens uit met als startinterval [0.5,1]. Je kunt natuurlijk - ook een andere functie proberen. Het programma zal je - waarschuwen indien je een verkeerd startinterval kiest. - - - 100 ' BISECTIE.BAS - 110 ' Zoek de oplossing van het probleem f(x) = 0 - 120 ' door gebruik te maken van de bisectiemethode - 130 ' Door Stefan Boer - 140 ' Sunrise Special #6 - 150 ' (c) Stichting Sunrise 1994 - 160 ' - 170 ' Zet hier de functie - 180 ' - 190 DEFFN F(X)=(X+1)*(X+1)*EXP(X*X-2)-1 - 200 ' - 210 CLS:PRINT"Bisectie":PRINT - 220 INPUT"a = ";A - 230 INPUT"b = ";B - 240 IF FNF(A)*FNF(B) >= 0 THEN PRINT"Kies een ander - interval!":GOTO 220 - 250 PRINT"a";TAB(20);"b";TAB(40);"c";TAB(60);"f(c)" - 260 C=(A+B)/2 - 270 PRINT A;TAB(20);B;TAB(40);C;TAB(60);FNF(C) - 280 IF ABS(A-B)<1E-12 THEN 310 - 290 Y=FNF(A)*FNF(C) - 300 IF Y<0 THEN B=C:GOTO 260 ELSE IF Y>0 THEN A=C:GOTO 260 - 310 PRINT:PRINT"Nulpunt:";C - - - F A L S E P O S I T I O N - - Bij bisectie maak je alleen gebruik van het teken van f(a) - en f(b), niet van de waarde. Je gebruikt dus niet alle - informatie. Door dit wel te doen kun je in minder stappen - het nulpunt bepalen. Je neemt als c het snijpunt met de x-as - van de lijn die de punten (a,f(a)) en (b,f(b)) met elkaar - verbindt. Dit algoritme heet false position. - - Ik zal nu de afleiding van de formule voor dit algoritme - laten zien. De parametrische voorstelling van de rechte lijn - is: - - y - f(a) = m (x - a) - - waarbij m de richtingsco�ffici�nt van de lijn is: - - f(b) - f(a) - m = ----------- - b - a - - Het invullen hiervan in de bovenste vergelijking en y = 0 - (we willen immers het snijpunt met de x-as hebben) levert - op: - - a f(b) - b f(a) - c = ---------------- - f(b) - f(a) - - Vervolgens doe je hetzelfde als bij bisectie. Het - stopcriterium van bisectie is hier echter ongeschikt, omdat - bij sommige functies de lengte van het interval niet kleiner - kan worden dan een bepaalde waarde (teken maar eens een - plaatje van de functie (1/x) - 1 met het interval [0,5]). We - kiezen daarom het stopcriterium |c(i+1) - c(i)| < epsilon - waarbij c(i+1) de nieuwe c is en c(i) de oude c. Epsilon is - de tolerantie. - - Ik heb ook dit algoritme in BASIC geprogrammeerd. Als je het - met dezelfde functie en hetzelfde startinterval probeert zul - je zien dat het in veel minder stappen convergeert dan - bisectie, het gaat echter niet veel sneller omdat het - berekenen van c meer tijd kost. Bij de meeste functies zal - false position minder stappen nodig hebben dan bisectie. - - - 100 ' FALSEPOS.BAS - 110 ' Zoek de oplossing van het probleem f(x) = 0 - 120 ' door gebruik te maken van de false position methode - 130 ' Door Stefan Boer - 140 ' Sunrise Special #6 - 150 ' (c) Stichting Sunrise 1994 - 160 ' - 170 ' Zet hier de functie - 180 ' - 190 DEFFN F(X)=X*X+LOG(X) - 200 ' - 210 CLS:PRINT"False position":PRINT - 220 INPUT"a = ";A - 230 INPUT"b = ";B - 240 PRINT:PRINT"a";TAB(20);"b";TAB(40);"c";TAB(60);"f(c)" - 250 CC=C:C=(A*FNF(B)-B*FNF(A))/(FNF(B)-FNF(A)) - 260 PRINT A;TAB(20);B;TAB(40);C;TAB(60);FNF(C) - 270 IF ABS(CC-C)<1E-12 THEN 300 - 280 Y=FNF(C)*FNF(A) - 290 IF Y<0 THEN B=C:GOTO 250 ELSE A=C:GOTO 250 - 300 PRINT:PRINT"Nulpunt:";C - - - Z O N D E R I N T E R V A L - - Dit waren twee algoritmes die werken met een interval. Er - zijn drie algoritmes die met ��n punt werken: vast punt, - Newton-Raphson en secant. De eerste twee zijn minder - geschikt om in BASIC te programmeren en de secantmethode - voegt niets nieuws toe. Ik zal dat hieronder per algoritme - uitleggen. - - - V A S T P U N T - - Bij het vast punt algoritme herschrijf je het probleem f(x) - = 0 in x = g(x). Vervolgens reken je net zo lang een nieuwe - x uit totdat het verschil met de vorige x kleiner is dan een - bepaalde tolerantie. Deze methode is niet in algemene zin - voor de computer te programmeren omdat de computer het - probleem niet kan herschrijven. Deze methode is sowieso niet - handig omdat de herschrijving aan de voorwaarde moet voldoen - dat g'(x) < 1 op een bepaald interval. Indien g'(x) > 1 dan - zal het divergeren. - - - N E W T O N - R A P H S O N - - Je neemt de raaklijn aan de functie in het punt (x,f(x)) en - je nieuwe benadering is het snijpunt van deze lijn met de - x-as. Dit herhaal je totdat de nieuwe benadering minder dan - een bepaalde tolerantie verschilt van de vorige. - - Deze methode heeft twee nadelen: je hebt de afgeleide nodig - om de raaklijn te bepalen en het gaat mis als f'(x) - toevallig 0 wordt. Dan is de raaklijn horizontaal en is er - geen snijpunt met de x-as. - - - S E C A N T - - Deze methode is gelijk aan de Newton-Raphson methode, alleen - schat je de raaklijn als een rechte lijn door het vorige - punt en het huidige punt. Hoewel de afleiding anders is, is - het resultaat hetzelfde als de false position methode. - - - T E N S L O T T E - - De volgende keer ga ik het waarschijnlijk hebben over - numeriek integreren. Ook daar zijn een paar handige - algoritmes voor die eenvoudig in BASIC kunnen worden - geprogrammeerd. Tot dan! - - Stefan Boer diff --git a/sunrise_special/6/Clock en batterij memory.md b/sunrise_special/6/Clock en batterij memory.md deleted file mode 100644 index 7ac59c8..0000000 --- a/sunrise_special/6/Clock en batterij memory.md +++ /dev/null @@ -1,427 +0,0 @@ - C L O C K E N B A T E R I J M E M O R Y - - - In de MSX2 en hoger zit een CLOCK-IC voor het bijhouden van - de tijd en datum. Omdat dit IC door een baterij wordt - gevoed, blijft het aktief ook als de computer wordt - uitgeschakeld. Ook is er een kleine hoeveelheid RAM voor het - bewaren van o.a de prompt en diverse screen instellingen. - - - C L O C K - I C F U N C T I E S - - Het IC heeft de volgende 3 functies: - - - CLOCK functies: - - - Bijhouden, lezen en schrijven van de TIJD en DATUM - - Keuze uit 24-uur/12-uur klok aanduiding. - - Bijhouden aantal dagen van de maand, en schrikkeljaar. - - - ALARM functies: - - - Als de actuele tijd is gelijk wordt aan de alarm tijd, - zal de clock een signaal doorgeven. - - - Baterij geheugen: - - - Bevat 26 x 4 bits registers, met diverse data - - MSX2 bewaart de volgende data in zijn geheugen: - - 1. "Adjust" - 2. Scherm keuze, "WIDTH" en kleuren - 3. "BEEP" patroon en volume - 4. Opstart scherm kleur - 5. Land code - 6. Paswoord - 7. BASIC prompt - 8. Opstart titel - - Van de laatste 3 (pasword, promt, title) kan er slechts 1 - aktief zijn. - - - S T R U K T U U R V A N C L O C K - I C - - Het clock-IC bestaat uit vier blokken zoals hieronder - afgedrukt. Elk blok bestaat uit 13 registers welke 4 bits - bevatten (LSB). Deze registers worden gespecificeerd van 0 - to 12. Daarnaast zijn er nog drie control registers (MODE, - TEST en RESET), waarmee diverse akties kunnen worden - uitgevoerd (register 13 to 15). De register in blokken - (0-12) en het MODE register (13) kunnen worden gelezen en - beschreven. De TEST (14) en RESET (15) registers kunnen - alleen worden beschreven. - - Blok 0 Blok 1 Blok 2 Blok 3 - (CLOCK) (ALARM) (RAM-1) (RAM-2) - 13 registers 13 registers 13 registers 13 registers - - r#13 MODE - r#14 TEST (write only) - r#15 RESET (write only) - - - M O D E R E G I S T E R - - Dit register heeft 3 functies, te weten: - - - Blok selecteren - Om een register te lezen of te beschrijven (0-12), moet er - van te voren wel worden aangegeven met welk blok er moet - worden gewerkt. De laagste twee bits bevatten het blok - nummer. Waneer eenmaal een blok is geselecteerd, kan een - register meerdere malen worden gebruikt zonder daarna weer - het blok nummer op te geven. - - Registers #13, #14 en #15 zijn altijd toegankelijk - onafhankelijk van het blok nummer. - - - ALARM aan/uit - Om het alarm aan of uit te zetten, moet bit 2 worden gezet - of gereset. "0" is uit. Omdat de standaard MSX2 de alarm - functies niet gebruikt, zal er niets gebeuren als de alarm - tijd is bereikt. Er wordt alleen ergens een signaal gegeven. - - - Stop CLOCK teller - Door bit 3 van het MODE register te resetten, zal de - klok-seconden teller stil gaan staan, en niet meer verder - tellen. Door dit bit weer te zetten, zal het tellen weer - doorgaan. - - MODE register opbouw: - - b3 b2 b1 b0 - r#13 TE AE M1 M0 - - M1/M0: Blok nummer - AE: Alarm aan/uit (0 is uit) - TE: Klok (0 is uit, in seconden) - - - T E S T R E G I S T E R - - Dit register (r#14) wordt gebruikt voor het direct verhogen - van de hoogste teller, en om na te gaan of de overdracht van - de tijd en datum juist is gedaan. Door een van de bits hoog - te maken, wordt er een puls van 2^14 (is 16384) Hz - doorgegeven aan de dag, uur, minuut en seconden tellers. - - TEST register opbouw: - - b3 b2 b1 b0 - r#14 T3 T2 T1 T0 (puls bits) - - T3: Dag - T2: Uur - T3: Minuut - T4: Seconden - - - R E S E T R E G I S T E R - - Het reset register (r#15) heeft de volgende functies: - - - Alarm reset - Als dit bit hoog wordt gemaakt, worden alle alarm register - ge-reset (nul). - - - Seconden afronden - Het klok IC telt ook in honderdste seconden. Om de seconden - exact te kunnen zetten, kunnen de nivo's voor de hele - seconden worden gereset (nul). Maak het bit hoog voor het - resetten. - - - Clock puls aan/uit - Het clock IC genereerd ook 2 lage pulsen. Een puls van 16Hz - of een puls van 1Hz. Door bit 2 "0" te maken zal de 16Hz - puls aan zijn. Door bit 3 "0" te maken zal de 1Hz puls aan - zijn. De MSX ondersteund dit echter niet, waardoor er - feitelijk niets mee kan worden gedaan. - - Reset register opbouw: - - b3 b2 b1 b0 - r#15 C1 C16 CR AR - - C1: 1Hz puls - C16: 16Hz puls - CR: Reset fracties voor seconden - AR: Reset alarm functies. - - - B L O K 0 / 1 - - T I J D , D A T U M E N A L A R M - - Blok schema: - - BLOK 0: KLOK - reg. Omschrijving. Dec. b3 b2 b1 b0 - (0) Seconden 1e x x x x 00-59 - (1) Seconden 2e . x x x - (2) Minuten 1e x x x x 00-59 - (3) Minuten 2e . x x x - (4) Uren 1e x x x x 00-23 - (5) Uren 2e . . x x - (6) Dag van week 1 . x x x 01-07 - (7) Dag 1e x x x x 01-31 - (8) Dag 2e . . x x - (9) Maand 1e x x x x 01-12 - (10) Maand 2e . . . x - (11) Jaar 1e x x x x 00-255 - (12) Jaar 2e x x x x (+80) - - Bits aangegeven met "." zijn altijd nul, en kunnen niet - worden gemodificeerd. - - Blok nul wordt gebruikt voor het lezen/schrijven van de tijd - en datum. De data is in max. 4 bits opgeslagen, waardoor een - ASCII teken in twee delen wordt opgesplitst. Bijvoorbeeld - een tijd eenheid bestaat uit 1x4 bits en 1x3 bits. Door bij - deze bits het ASCII teken "0" er bij op te tellen, onstaat - er 1 decimaal van een getal. - - Voorbeeld: We willen de tijd in uren weten. - Als we uit blok 0 dan de volgende register lezen; - - (5) +"0" 2e decimaal (wordt als eerste afgedrukt!) - (4) +"0" 1e decimaal (wordt als tweede afgedrukt!) - - Door deze twee ASCII waarden achterelkaar af te drukken, is - de tijd in uren bekend. - - Het jaar dat wordt bijgehouden, start bij 1980, dus moet er - bij de tweede decimaal "8" bij worden opgeteld in plaats van - "0". De datum zoals we die hier in Nederland afdrukken is - meestal van de volgende orde: - - Dag/Maand/Jaar - - De dag van de week wordt bijgehouden van 0 tot en met 6. - Deze wordt vernieuwd waneer de datum ook wordt vernieuwd. - - - BLOK 1: ALARM - reg. Omschrijving. Dec. b3 b2 b1 b0 - (0) ---- 1e x x x x - (1) ---- 2e . x x x - (2) Minuten 1e x x x x 00-59 - (3) Minuten 2e . x x x - (4) Uren 1e x x x x 00-23 - (5) Uren 2e . . x x - (6) Dag van week 1 . x x x 01-07 - (7) Dag 1e x x x x 01-31 - (8) Dag 2e . . x x - (9) ---- 1e x x x x - (10) 12 of 24 Uur 2e . . . x - (11) Schrikel jaar 1e . . x x 00-03 - (12) ---- 2e x x x x - - Het alarm kan alleen worden opgegeven in dagen, uren en - minuten. Dit blok bevat ook nog 2 register die betreking - hebben op de tijd aanduiding, en het schrikkeljaar. - - - 12 of 24 uur selectie - Er kunnen twee klok tijden worden geselecteerd; de een is - een 24-uurs aanduiding, welke de tijd in de middag/avond - weergeeft als 13:00, en de andere en een 12-uurs aanduiding, - welke het als 1 p.m. aangeeft. Door bit 0 van r#10 van blok - 1 hoog te maken, wordt er voor 24-uur gekozen. - - b3 b2 b1 b0 - r#10/B1 . . . TM - - TM: 0: 12 uren, 1: 24 uren. - - Als er voor 12-uren wordt gekozen, zal b1 van r#5 (blok 1) - aangeven of het 's morgens of 's middags is. - - b3 b2 b1 b0 - . . HR . - - HR: 0: Voor de middag (am), 1: namiddag (pm). - - - Schrikkeljaar. - - Register #11 houd bij of er dit jaar een schrikkel jaar is - of niet. Als dit zo is, zal de inhoud van dit register nul - zijn. Aangezien een schrikkeljaar om de vier jaar plaats - vindt (februari heeft dan 29 dagen), zal dit een 2 bits - teller zijn (0-3). - - - I N H O U D C L O C K - M E M O R Y - - blok twee en drie van het clock-IC wordt gebruikt voor de - 13x4 bits baterij geheugen blokken. Deze zien er als volgt - uit: - - - Inhoud blok 2 - - reg. b3 b2 b1 b0 - (0) -- ID -- - (1) X-adjust (-8 tot +7) - (2) Y-adjust (-8 tot +7) - (3) . . Interl Screen - (4) Width (laage bits) - (5) Width (hoge bits) - (6) Voorgrond kleur - (7) Achtergrond kleur - (8) Rand kleur - (9) Cass spd Pinter Key Clk Key ON/OFF - (10) BEEP soort Beep Volume - (11) . . Titel kleur - (12) Native Code - - Ik denk dat dit blok wel voor zich spreekt. - - - Inhoud blok 3 - - Dit blok bestaat ook nog eens uit 3 sub-bloks. Deze kan - worden gekozen door een ID code naar block drie te - schrijven, hierna kan een sub-blok worden - gelezen/beschreven. - - Sub-blok 1, openings titel (6 karakters) - reg. b3 t/m b0 - (0) ID:0 - (1) 1e karakter (laag) - (2) 1e karakter (hoog) - . - . - . - (11) 6e karakter (laag) - (12) 6e karakter (hoog) - - Sub-blok 2, password - reg. b3 t/m b0 - (0) ID:1 - (1) gebruik ID:1 - (2) gebruik ID:2 - (3) gebruik ID:3 - (4) Paswoord * - (5) ,, - (6) ,, - (7) ,, - (8) Key cartridge flag - (9) Key cartridge waarde - (10) ,, - (11) ,, - (12) ,, - - * Het paswoord word gecompreseerd opgeslagen in 4x4 bits. - Hoe dit wordt opgeslagen is mij niet bekend. Waar de rest - voor dient zou ik ook precies weten. Gezien ik deze blokken - toch nooit gebruik. - - Sub-blok 3, Basic prompt (6 karakters) - reg. b3 t/m b0 - (0) ID:2 - (1) 1e karakter (laag) - (2) 1e karakter (hoog) - . - . - . - (11) 6e karakter (laag) - (12) 6e karakter (hoog) - - De registers van sub-blok 1 & 3 spreken voor zichzelf. - - - T O E G A N G T O T H E T C L O C K - I C - - In het MSX SUB-ROM Bios zitten 2 routines voor de toegang - van deze clock IC. Om deze aan te roepen moet de inter-slot - call routine &h1F5 worden gebruikt. Deze routines gebruiken - de volgende entries: - - - REDCLK (01F5/SUB), Read CLOCK-IC data - In: C, register en block. - Uit: A, register data. - Funtie: Lees CLOCK-IC register. - - - WRTCLK (01F9/SUB), Write CLOCK-IC data - In: C, register en block. - A, register data. - Funtie: Schrijf naar CLOCK-IC register. - - Het C register bevat twee waarden; het register/sub-blok en - het blok nr. De volgende bits worden gebruikt: - - b7 b6 b5 b4 b3 b2 b1 b0 - C reg. . . M1 M2 A3 A2 A1 A0 - - M1/M2: Blok nr. - A3-A0: Register/sub-blok nr - - Maar natuurlijk kan er ook gebruik worden gemaakt van de OUT - poorten (dit doen de BIOS routines ten slotte ook). Maar - aangezien de BIOS routines vaak meer doen dan gedaan hoeft - te worden, kunnen er beter eigen routines worden gebruikt. - Om namelijk meerdere keren een register uit het zelfde blok - te kunnen lezen/schrijven, hoeft er maar 1 keer te worden - opgegeven wat voor (sub) blok er moet worden gebruikt. Bij - de bios routines wordt dit altijd het blok gezet, wat dus - tijds verlies is. - De poorten die het IC gebruikt zijn: - - &hB4 - register/block nr - &hB5 - Data. - - Hieronder zijn enkele routines geplaats als voorbeeld voor - het lezen, schrijven van het IC. - - ;+----- Clock Routines -----+ - ; written by: SHADOW from FUZZY LOGIC. - ; last update: 29/02/94 for sunrise special. - - ; Read Clock_Register - ; note: Set block nr with "SC_BLK" first! - ; In: A, Clock register/block ID to read - ; Out: A, clock data - RD_CLK: DI - OUT (&HB4),A - IN A,(&HB5) - AND &H0F - EI - RET - - ; Write Clock_Register - ; note: Set block nr with "SC_BLK" first! - ; In: A, clock register/block ID to write - ; B, register data - WR_CLK: DI - OUT (&HB4),A - IN A,(&HB5) - AND &H0F - EI - RET - - ; Set Clock_Block - ; In: B, bloc nr (0-3) - SC_BLK: CALL RC_MOD - AND &H0C ; save count/alarm bits - OR B ; add block - DI - OUT (&HB5),A - EI - RET - - ; Read Clock_Mode reg - RC_MOD: LD A,13 - JP RD_CLK - - - Dit zijn feitelijk alle routines die nodig zijn voor het - gebruik van de CLOCK-IC. Op deze special staat een file - "CLOCK-IC.asc" die een paar routines bevat die de tijd en - datum op het beeld zet. - Voor het beschrijven van het MODE register is het wel van - belang dat de rest van de bits bewaard blijven, dus lees - eerst even dit register uit met "RC_MOD". - - Mocht iemand weten hoe het pasword-sub-blok wordt beruikt, - laat het dan even weten, want zelf sta ik voor een raadsel. - - R�man van der Meulen diff --git a/sunrise_special/6/Cursus modula deel 1.md b/sunrise_special/6/Cursus modula deel 1.md deleted file mode 100644 index dda23f5..0000000 --- a/sunrise_special/6/Cursus modula deel 1.md +++ /dev/null @@ -1,282 +0,0 @@ - C U R S U S M O D U L A - 2 ( 1 ) - - - I N L E I D I N G - - Aangezien het niet mogelijk is om in ��n deel iemand die - helemaal niets van Turbo Pascal weet Modula-2 te leren ga ik - de volgende keer van nul af aan beginnen. Dit deel van de - cursus is daarom bedoeld voor MSX'ers die al ervaring hebben - met Turbo Pascal. - - Als je niet wilt wachten tot Special #7 dan kun je - natuurlijk altijd eens inloggen bij de Games BBS, daar is - een Engelstalige Modula-2 cursus te vinden en een flinke - hoeveelheid voorbeeldsources. Bovendien is er een .PMA te - vinden met uitleg van Pierre Gielen over het naar modulevorm - overzetten van ML-routines. - - - O P B O U W - - Onderstaand voorbeeld laat de opbouw van een Modula-2 source - zien. Het programma vult een array met wortels en drukt dat - array vervolgens af. Wat het programma doet is niet boeiend, - het gaat om de opbouw. - - - MODULE Opbouw; - - (* - Auteur : Stefan Boer - Versie : 1.0 - Last updated: 09/06/94 - *) - - - FROM MathLib IMPORT - Sqrt; - - - CONST - AantalWortels = 10; - - - TYPE - WortelIndexType = CARDINAL [1..AantalWortels]; - WortelLijstType = ARRAY WortelIndexType OF REAL; - - - VAR - WortelLijst: WortelLijstType; - - - PROCEDURE BerekenWortels(VAR WortelLijst: WortelLijstType); - - VAR - i: WortelIndexType; - - BEGIN - FOR i := 1 TO AantalWortels DO - WortelLijst[i] := Sqrt(FLOAT(i)); - END; - END BerekenWortels; - - - PROCEDURE PrintWortels(WortelLijst: WortelLijstType); - - VAR - i: WortelIndexType; - - BEGIN - FOR i := 1 TO AantalWortels DO - WRITELN(WortelLijst[i]); - END; - END PrintWortels; - - - (* Hoofdprogramma *) - - BEGIN - BerekenWortels(WortelLijst); - PrintWortels(WortelLijst); - END Opbouw. - - - Merk op dat de definitie van MathLib afwijkend is van wat - Wirth voorschrijft bij Turbo Modula-2! Wirth noemt hem - MathLib0 en de vierkantswortel heet bij hem sqrt, niet met - een hoofdletter dus! - - Pascalkenners zal de volgende dingen opvallen: - - - De source begint niet met PROGRAM maar met MODULE - - ENDs van modules en procedures zijn gelabeld - - De syntax van het FOR-statement is anders - - Sqrt moet worden ge�mporteerd - - Declaratie van subrange en array gaat anders - - Ik zal nu een aantal verschillen tussen Turbo Pascal en - Turbo Modula-2 bespreken. - - - C O M P O U N D S T A T E M E N T - - Bij Turbo Pascal ziet een IF statement er bijvoorbeeld zo - uit: - - IF boolean expressie THEN - statement1 - ELSE - statement2; - - Om toch meerdere statements te kunnen gebruiken heeft Wirth - het compound statement bedacht, door BEGIN en END om een - groep statements te zetten worden ze samen ��n statement. - - Dit kan erg verwarrend zijn, vooral als je een zootje maakt - van de layout. Bijvoorbeeld: - - IF a = 3 THEN - WRITE('a is 3'); - WRITE('hallo'); - - Door de layout suggereer ik hier dat het tweede WRITE - statement alleen wordt uitgevoerd als a gelijk is aan 3. Dit - is niet zo, alleen het eerste WRITE statement hoort bij de - IF. De juiste Pascal formulering zou zijn: - - IF a = 3 THEN - BEGIN - WRITE('a is 3'); - WRITE('hallo'); - END; - - Hier hebben we dus een compound statement gebruikt. In - Modula-2 is het veel logischer: - - IF boolean expressie THEN - statement sequence 1 - ELSE - statement sequence 2 - END; - - Waarbij een 'statement sequence' bestaat uit 0 (!), 1 of - meer statements! Er staat dus NOOIT een BEGIN en ALTIJD een - END! Bovendien MOGEN er in Modula-2 altijd ; geplaatst - worden. Bij Pascal is dat niet zo. Bijvoorbeeld: - - IF a = 3 THEN - WRITE('hallo'); - ELSE - WRITE('doei'); - - geeft een foutmelding in Pascal, de ; achter WRITE('hallo') - is in Pascal niet toegestaan. In Modula-2 moet er natuurlijk - nog een END achteraan en de puntkomma mag wel! (Maar hoeft - niet.) - - Omdat een puntkomma achter een statement in Modula-2 altijd - mag zet ik er ook altijd ��n, dan kan ik me nooit vergissen! - - Bij WHILE, FOR en WITH gaat het net zo. Dus: - - WHILE boolean expressie DO - statement sequence - END; - - FOR loopvariable := startwaarde TO eindwaarde DO - statementsequence - END; - - WITH record-variabele DO - statementsequence - END; - - - T Y P E S - - Turbo Modula-2 kent de volgende atomaire types: - - BITSET standaard settype - BOOLEAN waar/niet waar - CHAR character - CARDINAL 0, 1, 2, ..., 65535 - INTEGER -32768, ..., 0, ..., 32767 - LONGINT - REAL single precision floating point (6 cijfers) - LONGREAL double precision floating point (14 cijfers) - - Voorbeelden van simple types: - - subrange: IndexType = CARDINAL [1..10]; - enumeration: StatusType = (Slecht, Matig, Redelijk, Goed); - - Voorbeelden van gestructureerde types: - - record: PatientType = RECORD - Temperatuur: REAL; - Bloeddruk : REAL; - END; - array: LijstType = ARRAY IndexType OF PatientType; - set: Verzameling = SET OF IndexType; - - Verder zijn er nog pointertypes en procuduretypes, maar daar - kom ik in een later deel van de cursus nog wel eens op - terug. - - - F U N C T I E S - - In Pascal ziet een functie er bijvoorbeeld als volgt uit: - - FUNCTION Kwadraat(x: REAL): REAL; - - BEGIN - Kwadraat := x * x; - END; - - In Modula-2 wordt dit: - - PROCEDURE Kwadraat(x: REAL): REAL; - - BEGIN - RETURN x * x; - END Kwadraat; - - Er zijn 3 belangrijke verschillen: - - 1) PROCEDURE in plaats van FUNCTION - 2) RETURN in plaats van functienaam := - 3) Bij een Modula-2 functie staan altijd haakjes, ook als er - geen parameters zijn! - - Met RETURN wordt ook meteen de functie be�indigd, RETURN - zonder iets erachter kan in een gewone procedure worden - gebruikt om uit de procedure te springen. - - - M C C A R T H Y - - Modula-2 gebruikt McCarthy evaluatie bij het evalueren van - boolean expressies. Dit komt erop neer dat de boolean - expressie niet verder wordt ge�valueerd dan nodig is. In - Pascal wordt de boolean expressie altijd helemaal - ge�valueerd! - - McCarthy evaluatie heeft geen nadelen, de voordelen zijn dat - het sneller is en dat onderstaand statement altijd goed - gaat: - - IF (n = 0) OR (a / n > 10) THEN ... - - Bij Turbo Pascal gaat dit fout, want bij het uitrekenen van - a / n wordt er door 0 gedeeld! Bij Modula-2 gaat het goed, - want als n gelijk is aan 0 dan wordt a / n niet meer - uitgerekend! - - - S T R E N G - - Modula-2 is strenger bij de controle op types. Operaties - zoals aftrekken, vermenigvuldigen, etc. mogen alleen maar - worden gedaan op gelijke types!!! - - Het onderstaande mag dus niet! - - VAR - x: INTEGER; - y: CARDINAL; - - WRITE(x*y); - - - T E N S L O T T E - - Dit waren in het kort de belangrijkste verschillen tussen - Turbo Modula-2 en Turbo Pascal. De volgende keer ga ik vanaf - het begin beginnen met een cursus gestructureerd - programmeren in Modula-2. - - Tot dan! - Stefan Boer diff --git a/sunrise_special/6/Een muis met een staartje.md b/sunrise_special/6/Een muis met een staartje.md deleted file mode 100644 index d6602eb..0000000 --- a/sunrise_special/6/Een muis met een staartje.md +++ /dev/null @@ -1,354 +0,0 @@ - E E N M U I S M E T E E N S T A A R T J E - - - (I/O Interface 2) - - Inderdaad, dit verhaal krijgt een staartje. Er is al eens - een tekst geschreven over het aansturen (en vooral lezen!) - van de mouse. Er zaten alleen wat nadelen aan de routine die - toen werd geschreven. Het werkte alleen in de Z80 stand, en - was nogal 'gevaarlijk' geschreven, doordat er rechtstreeks - in de routines werd ge'poked' voor het uitlezen van zowel - poort 1 als poort 2. - - In deze tekst hoop ik wat meer duidelijkheid te kunnen - scheppen in het hele I/O gebeuren wat betreft de mouse, en - een betere routine te leveren (die NIET gebruik maakt van de - standaard MSX ROM BIOS!). Er wordt hier gebruikt gemaakt van - de PSG poorten, dus raad ik aan de tekst over het gebruik - van de joystick in ML (special #5) eerst (nog) eens door te - lezen. - - - M E N N E M E . . - - Om een mouse te gebruiken moet er toch eerst worden gezocht - of er wel een mouse aanwezig is. Deze kan aangesloten zijn - in zowel poort 1 als 2. Om aan te geven in welke poort we - willen werken, moeten we van PSG r#15 het 6e bit (lees ook - artikel over joysticks) aan of uit zetten. (0=poort 1, - 1=poort 2). - - Om aan te geven dat we gebruik willen gaan maken van de - mouse, moeten we (weer afhankelijk van welke poort) bit 4 of - bit 5 van r#15 zetten. Deze bits zijn verbonden met de 8e - pen van de game-poorten (deze zitten, zoals bekend?, - hardware matig aan de buitenkant van uw MSX). - - Als er aan uw MSX geen mouse hangt, maar een programma neemt - aan van wel, en er wordt mouse data gelezen, bijvoorbeeld in - en tekenprogramma, dan zal het teken-pijltje langzaam met - stappen van 1 naar de rechter onderhoek van uw scherm - glijden. Van dit proces kunnen we gebruik maken om te kijken - of er wel of niet een mouse aanwezig is! - - Als we een aantal keren gaan kijken of de mouse offsets X en - Y iedere keer met 1 worden verhoogt, dan zal er blijkbaar - geen mouse aanwezig zijn. Als we dit 1 keer gaan testen, dan - is er het gevaar dat de gebruiker de mouse beweegt op het - moment van testen, en dat deze beweging precies overeenkomt - met het al eerder genoemde proces. Dus is het verstandig om - meerdere malen dit te gaan testen. Want het is praktisch - onmogelijk om precies de X en Y met 1 te laten verhogen voor - meerdere malen achter elkaar! - - - Z 8 0 O F R 8 0 0 - - Om een mouse te lezen, moeten er vertragings routines worden - gebruikt, omdat de mouse een relatief traag apparaatje is - ten opzichte van de CPU (Z80 of R800). - Met andere woorden: Er moet gewacht worden op de mouse tot - dat deze klaar is met het verzenden van data. Daar er geen - 'strobe' (klaar voor aktie signaal) wordt gegeven, moeten we - gewoon de CPU een tijdje laten wachten. - - Hier stuiten we op een probleem. We kunnen namelijk wachten - door middel van interrupts of gewoon een vertragings lus. - Maar een interrupt duurt veel te lang voor het wachten op de - muis (1/50 of 1/60 seconde). Daarom kiezen we voor een - vertagings lus. Maar omdat de Z80 op 3.5 MHz loopt en de - R800 op 7,4 MHz, moeten we 2 verschillende routines maken. - Tijdens het installeren van de mouse kunnen we hier gewoon - even kijken wat voor CPU er aan boord is en na aanleiding - van dit een pointer 'poken'. - - Het feitelijk uitlezen gaat via de PSG poorten. De data die - gelezen kan worden zijn altijd in afstanden (offsets) ten - opzichte van de laatst gelezen waarde. Dus de afstand dat u - de mouse beweegt. Door deze bij de vorige coordinaten op de - tellen, hebt u de nieuwe coordinaten. - De data die wordt gegeven zijn slechts 4 bits, daar er 8 - nodig zijn voor het bereik van 0-255 moet er dus 2 keer - gelezen worden om een 8 bits offset te krijgen. Dit kan door - gewoon twee keer achter elkaar r#15 te lezen. De eerste keer - worden de 4 hoogste bits gegeven, daarna de 4 laagste. De - offsets worden in bits 0-3 geplaats. De mouse doet er echter - langer over om de 4 hoogste X-offset bits door te geven dan - de 4 laagste, dus zal de eerste keer dat r#15 wordt gelezen - langer moeten worden gewacht. De Y offsets worden altijd - even snel doorgegeven. Een voorbeeld van twee wacht - routines: - - ; - Delay routs - - ; Z80. - ; In: B, delay length - DL_Z80: DJNZ DL_Z80 - RET - - ; (R800) - ; In: C, delay lenth - DL_R80: IN A,(&HE6) ; turbo R timer - LD B,A - DR80.0: IN A,(&HE6) - SUB B - CP C - JP C,DR80.0 - RET - - Bij de MSX tubo R wacht routine wordt gebruikt gemaakt van - een razend snelle teller die in deze pracht machine zit - ingebouwd. Bij de eerste keer uitlezen van de mouse zullen - de volgende vertragingen moeten worden gebruikt (minimaal): - Z80 - B,40 - R800 - C,20 - - De volgende keren dat gelezen moet worden kan de vertraging - korter zijn namelijk: - Z80 - B,7 - R800 - C,6 - - - P A D D L E U I T L E Z E N - - De volgende data gebruiken we bij de mouse acties. Deze - staan origineel ook in het System variabelen gebied, dus - waarom zouden we die niet gebruiken? - - ; Mouse vars. - MOUSID: EQU &HFAFD ; ID code: 0=Niet aanwezig - MSEOFS: EQU &HFAFE ; Mouse offsets X en Y - MOUSXY: EQU &HFB00 ; Mouse X en Y positie - MSEPRT: EQU &HFC82 ; Mouse Poort (0=niet, - ; &H10=poort 1, &H60=poort2) - - - De data die de padle geeft is ook nog een keer negatief dus - als de mouse naar boven wordt bewogen, zal bijvoorbeeld de Y - offset +20 zijn in plaats van -20. Zowel de X als de Y - offsets zijn negatief. - Een dergelijke routine om de beide offsets te lezen kan er - als volgt uit zien: - - ; Get paddle offset. - ; In: [MSEPRT], port nr. (see mouse vars.) - ; Out: [MSEOFS]/HL, YYXX ofs. (A, Y ofs.) - GETPAD: PUSH BC - PUSH DE - - LD DE,(MSEPRT) ; E=Mouse poort. - LD A,15 ; Lees PSG r#15 - CALL RD_PSG - AND &B10001111 ; bewaar rest bits. - OR E ; Maak nr bit "1" - LD E,A - - ; X offset - LD B,40 ; Eerste vertraging Z80 - LD C,20 ; ,, ,, R800 - CALL GPAD.2 ; MSB - CALL GPAD.0 ; LSB - LD L,A ; L=X offset - - ; Y offset - CALL GPAD.1 ; MSB - CALL GPAD.0 ; LSB - LD H,A ; H=Y offset - LD (MSEOFS),HL ; bewaar beide offsets - - EI - POP DE - POP BC - RET - - ; Shift bits (LSB -> MSB), read LSB and make offset neg. - GPAD.0: RLCA - RLCA - RLCA - RLCA - AND &HF0 - LD D,A - CALL GPAD.1 ; Lees LSB - OR D ; Voeg MSB hier aan toe - NEG ; Maak offset negatief. - RET - - ; Read paddle data - ; In: [MSEPRT], mouse port (see mouse vars.) - ; (B/C, delay first time -> only in GPAD.2) - ; Out: A, offset in LSB - GPAD.1: LD BC,&H0706 ; Vertraging variables - GPAD.2: LD A,15 ; Schrijf naar r#15 - CALL WR_PSG - LD A,(MSEPRT) - AND &H30 ; Alleen mouse bits - XOR E - LD E,A - GP_DL#: CALL xxxx ; Hier wordt de vertragings - pointer gepoked tijdens - de mouse installatie - (Z80 of R800) - LD A,14 ; Lees r#14 (offset data) - CALL RD_PSG - AND &H0F ; alleen LSB - RET - - Routines voor het schrijven of lezen van de PSG kunnen er - als volgt uit zien: - - ; Read PSG. - ; In: A, port nr - ; Out: A, data - RD_PSG: DI - OUT (&HA0),A - IN A,(&HA2) - EI - RET - - ; Write to PSG. - ; In: A, port nr. E, port data - WR_PSG: DI - OUT (&HA0),A - LD A,E - OUT (&HA1),A - EI - RET - - Deze laatste twee routines zijn feitelijk het zelfde als die - in het MSX ROM BIOS aanwezig zijn, maar aangezien ik hier - (liever) geen gebruik van maak heb ik ze hier maar - bijgevoegd. - - Nu hebben we dus een routine die de paddle data kan lezen. - Om het vertragins pointer adres te poken, moet er nog een - mouse installatie routine worden geschreven. Deze moet dus - kijken of we met een Z80 of een R800 CPU te maken hebben. - Door het adres &h2D uit te lezen weten we of we met een - turbo R computer of een MSX 1/2/2+ te maken hebben. Indien - het om een MSX turbo R gaat moet er ook nog gekeken worden - in welke CPU mode hij (of is het een zij?) op dit moment - staat. - - ; Install Mouse - MOUSIN: LD A,255 - LD (MOUSID),A - LD HL,DL_Z80 ; vertraging pointer Z80 - LD A,(&H2D) ; turbo R ? - CP 3 ; nee.. - JP C,MSIN.0 - CALL &H0183 ; R800 aan? - AND A - JP Z,MSIN.0 ; nee.. - LD HL,DL_R80 ; ja, turbo R wacht routine - MSIN.0: LD (GPW_#A+1),HL - RET - - Om te kijken in welke CPU mode de turbo R staat heb ik nu - wel voor de ROM routine gekozen. Om de CPU te wisselen moet - er namelijk van alles worden bewaard zoals de register en - stack pointer etc. Om de CPU te lezen hoeft dit niet, maar - aangezien ik de CPU switch routine ook niet heb herschreven, - leek mij het hier ook niet echt nootzakelijk. - - - M O U S E D E T E C T I E - - Nu zijn alle routines klaar voor het lezen van de paddle - waarde. Deze routines kunnen we nu gebruiken voor - bijvoorbeeld het controleren of de mouse aanwezig is in een - game-poort. De volgende routine lost dit voor ons op: - - ; Check mouse. - ; Out: [MOUSEID]: 0=not found, 255=found and installed. - ; Cy: 0=found, 1=not found. - CHMOUS: CALL MOUSIN ; instaleer wacht lus. - LD A,&H10 ; probeer eerst poort 1... - LD (MSEPRT),A - CALL CHMS.0 - JP NC,MOUSIN ; gevonden. - - LD A,&H60 ; niet, dan poort 2 - LD (MSEPRT),A - CALL CHMS.0 - JP NC,MOUSIN ; gevonden. - - XOR A ; niet gevonden. - LD (MOUSID),A - LD (MSEPRT),A - SCF ; Cy=1 - RET - - CHMS.0: LD B,40 ; kontroleer 40 x - CHMS.1: PUSH BC - CALL G_PADL ; Y-offset - CP 1 ; stap+1? - JP NZ,CHMS.2 ; nee, dus mouse aanwezig - LD A,L ; X-offset - CP 1 ; stap+1? - JP NZ,CHMS.2 ; nee, dus mouse aanwezig - POP BC ; nog een keer.. - DJNZ CHMS.1 - SCF ; Cy:1 (niet gevonden) - RET - CHMS.2: POP BC ; gevonden - AND A ; Cy:0 - RET - - Na het aanroepen van deze routine kan er op drie manieren - worden gecontroleerd of de mouse al dan niet aanwezig is. - Als de carry (Cy) hoog is, zal deze niet zijn gevonden. De - variable MOUSID zal "0" zijn als de mouse niet aanwezig is - (255 is wel aanwezig). Ook kan de variable MSEPRT worden - gelezen. Is deze "0" dan is de mouse niet gevonden, anders - bevat deze de mouse poort nummer data. - Meer is eigenlijk niet nodig, om de X/Y positie te - verkrijgen kunnen gewoon de X en Y offsets bij de originele - coordinaten worden op geteld. Een routine die dat ook voor - ons regelt: - - ; Read any mouse, and set X,Y pos. - ; Out: [MOUSXY]/HL, XXYY position. - ; Cy: 1, mouse not found - RDMOUS: LD HL,0 - LD (MSEOFS),HL - LD A,(MOUSID) ; Controleer of er een mouse - AND A ; aanwezig is. - SCF ; Zet carry flag. - RET Z - - CALL GETPAD ; Lees paddle - LD A,(MOUSXY) ; Originele X positie. - ADD A,L ; + X offset - LD L,A - LD (MOUSXY),A - LD A,(MOUSXY+1) ; Originele Y positie. - ADD A,H ; + Y offset - LD H,A - LD (MOUSXY+1),A - AND A ; Wis carry flag - RET - - Met deze routines moet het mogelijk zijn om 100% gebruik te - kunnen maken van de mouse. De twee vuurknoppen worden - natuurlijk op de zelfde manier gelezen als de joystick (zie - ook I/O interface deel 1, RDTRG1 / RDTRG2). - - Ik stimuleer het enorm om in software pakketten de mouse - zoveel mogelijk te kunnen gebruiken. Zowel in utilities als - in demos! (zoals bijvoorbeeld in de MB muzax reeks). Want de - mouse is toch een prima stukje hardware voor interactieve - doeleinden. In screen 0 kan ook uitstekend de mouse worden - gebruikt. Deel gewoon de X en Y coordinaten door 8 voor de - juiste posities. - - R�man van der Meulen diff --git a/sunrise_special/6/Files voor MSX View.md b/sunrise_special/6/Files voor MSX View.md deleted file mode 100644 index 6b06e6d..0000000 --- a/sunrise_special/6/Files voor MSX View.md +++ /dev/null @@ -1,23 +0,0 @@ - F I L E S V O O R M S X - V I E W - - - Jan van Valburg heeft de volgende files gemaakt of er een - Nederlandse handleiding bijgemaakt: - - VIEW-01.PMA: Een printerdriver voor de EPSON LQ-400. - VIEW-02.PMA: Een programma om MIDI-files af te spelen onder - MSX-View. - VIEW-03.PMA: Hiermee is het mogelijk om C programma's voor - onder MSX-View te schrijven. - VIEW-04.PMA: Een aantal stempels voor MSX-View. - VIEW-05.PMA: Een demoversie van de patch naar Engels van - MGF. - - De volgende 2 files zijn tenslotte nog andere applicaties - voor MSX-View, compleet in het Japans: - - BOMBS.PMA : Bombsweeper voor MSX-View. - MEIDOSS.PMA: Een programma waarmee iets met samples mogelijk - is. - - Kasper Souren diff --git a/sunrise_special/6/Gestruktureerd programmeren in ML deel 2.md b/sunrise_special/6/Gestruktureerd programmeren in ML deel 2.md deleted file mode 100644 index 806e3e7..0000000 --- a/sunrise_special/6/Gestruktureerd programmeren in ML deel 2.md +++ /dev/null @@ -1,205 +0,0 @@ - G E S T R U C T U R E E R D - - P R O G R A M M E R E N I N M L ( 2 ) - - - Na de inleiding van Alex van de vorige keer gaan we nu echt - beginnen. De methode die ik ga uitleggen in dit deel en de - volgende delen heet stapsgewijze verfijning of top-down. Ik - zal het hier toespitsen op ML, in de Modula-2 cursus komt in - principe hetzelfde verhaal, alleen dan voor Modula-2. - - - S T A P S G E W I J Z E V E R F I J N I N G - - Het principe is zeer simpel. Je wilt een probleem oplossen. - Je schrijft het probleem eerst in pseudo-code op, meestal - zal dat een soort krom Nederlands zijn. Je splits het - probleem hierbij op in ongeveer drie of vier deelproblemen. - - Vervolgens leg je voor ieder van de deelproblemen stap voor - stap nader uit wat er wordt bedoeld. Je gaat elk - deelprobleem weer op dezelfde manier behandelen, totdat je - op een gegeven moment op zo'n laag niveau bent aangeland dat - je het zonder problemen in ML kunt zetten. Het verfijnen - gaat net zo lang door totdat een compleet ML programma is - ontstaan. - - Het voordeel van deze methode is dat je maar een klein - gedeelte van het totale probleem tegelijk hoeft te overzien - in ML, het zal je op dat moment een zorg zijn hoe de rest is - geprogrammeerd. Hierdoor blijft het overzichtelijk. - - In Modula-2 heb je procedures en parameters om dit allemaal - in goede banen te lijden, in ML zul je dit allemaal zelf - moeten doen. Vooral de parameters (lees: registers) zijn - nogal eens een probleem, je moet goed opletten welke - registers je moet bewaren en welke je rustig kunt - veranderen. - - Het is belangrijk dat je er bij het schrijven van een - routine vanuit gaat dat de routines die je daarin aanroept - al werken. Dat is dus niet zo! Je werkt topdown, van boven - naar beneden dus en je schrijft dus eerst de hoofdroutine, - dan de routines die door de hoofdroutines worden - aangeroepen, dan de routines die weer door die routines - worden aangeroepen, etc. - - Een probleem daarbij is dat je vantevoren vaststelt via - welke registers de in- en uitvoer van een routine op een - lager niveau gaat, en het kan gebeuren dat bij het schrijven - van die routine blijkt dat je beter andere registers had - kunnen kiezen. Hier is weinig aan te doen, maar door - ervaring zul je dit soort fouten steeds minder maken. - - - V O O R B E E L D - - Om te laten zien wat ik bedoel zal ik het eerste gedeelte - van de hoofdroutine van een willekeurig spel bespreken. Ik - zal hier nog niet tot het laagste niveau afdalen, dat komt - later. - - Stel we hebben een spel met een speler en vijanden, als de - speler tegen een vijand aanloopt moet hij ermee vechten. Het - scherm scrollt niet maar werkt met 'flipscreens' (als je het - scherm uitloopt komt het volgende scherm). - - De eerste aanzet voor een hoofdlus: - - Beweeg vijanden - Beweeg speler - Ga zonodig naar ander scherm - Zet de vijanden en speler op het scherm - Kijk of de speler ��n van de vijanden raakt - Herhaal - - Dit is vrij eenvoudig in ML om te zetten: - - Hoofdlus: CALL MoveEnemies - CALL MovePlayer - CALL OtherScreen - CALL PutSprites - CALL CheckHit - JR Hoofdlus - - Dit is erg overzichtelijk en het is zeer eenvoudig om nog - iets extra's toe te voegen. Als er bijvoorbeeld een - tijdslimiet is dan wordt het bijvoorbeeld: - - Hoofdlus: CALL MoveEnemies - CALL MovePlayer - CALL OtherScreen - CALL PutSprites - CALL CheckHit - CALL CheckTimeLimit - JR NC,Hoofdlus - CALL OutOfTime - - Waarbij de routine CheckTimeLimit een carry retourneert - indien de tijd is verstreken en OutOfTime een melding op het - scherm zet dat de tijd op is. Het is tijd voor de volgende - stap in het verfijningsproces, de routine MoveEnemies. Het - is misschien erg voor de hand liggend maar de eerste aanzet - daarvoor is: - - FOR i = 1 TO Aantal vijanden - Beweeg vijand nummer i - NEXT - - Soms is het handig om wat BASIC (of bijvoorbeeld Modula-2) - te gebruiken in de pseudo code, dat is korter en - duidelijker. Dit is natuurlijk zeer simpel in ML te - programmeren: - - MoveEnemies: LD A,(AantalEnemies) - LD B,A - MoveEnemies_Lus: CALL MoveEnemy - DJNZ MoveEnemies_Lus - RET - - Het ontwerp van MoveEnemy ziet er bijvoorbeeld zo uit: - - Bepaal welke richting de vijand op moet - Kijk of dat mogelijk is (i.v.m. obstakels) - Zo ja, pas dan de co�rdinaten aan in de gewenste - richting - - Ook dit is weer eenvoudig in ML om te zetten: - - ; MoveEnemy - ; Beweeg een vijand - ; In : B = nummer van vijand - ; Uit: B is ongewijzigd - - MoveEnemy: CALL WhichDirection - CALL CheckIfPossible - RET C - CALL ChangeCoors - RET - - Waarbij de headers van de routines WhichDirection, - CheckIfPossible en ChangeCoors er zo uitzien: - - ; WhichDirection - ; Bepaal welke richting een vijand op moet gaan - ; In : B = nummer van vijand - ; Uit: A = richting - ; B is ongewijzigd - - ; CheckIfPossible - ; Bepaal of het mogelijk is voor monster B om in richting A - ; te bewegen - ; In : A = richting, B = monster - ; Uit: carry = niet mogelijk/no carry = wel mogelijk - ; A en B zijn ongewijzigd - - ; ChangeCoors - ; Monster B beweegt in richting A - ; In : A = richting, B = monster - ; Uit: coordinaten zijn gewijzigd - ; B is ongewijzigd - - En zo kun je dus verder gaan totdat je bij de echte code - uitkomt, ChangeCoors is daar bijvoorbeeld al een geschikte - kandidaat voor. - - - L A Y O U T - - De gebruikte layout is zeer belangrijk voor de leesbaarheid - van je programma. Zelf programmeer ik 'case sensitive', ik - zet alle Z80-instructies in hoofdletters en labels beginnen - met een hoofdletter en zijn voor de rest kleine letters - behalve als er een nieuw woord begint in een label. Ik werk - met een labellengte van 16 tekens zodat ik fatsoenlijke - namen voor routines kan gebruiken en ook nog ruimte heb om - er dingen als "_Lus" achter te plakken. - - De TABs zijn als volgt ingesteld: - - 1 label - 19 instructie - 25 operand - 43 commentaar - - Dus bijvoorbeeld: - - Schermopbouw_Lus: LD A,AantalKolommen ; commentaar - - Het lijkt hier alsof de ruimte voor commentaar erg klein is - maar normaal gesproken heb je natuurlijk 80 kolommen (hier - 60). Je kunt zelf je eigen layout kiezen, als je hem maar - consequent volhoudt en er geen puinhoop van maakt. Ik heb - deze layout bij WR gebruikt en dat is erg goed bevallen. - - Het voordeel van lange labels blijkt al snel als je gaat - bedenken wat het label Schermopbouw_Lus in WB-ASS2 zou - worden: SCOB_L of zoiets. Niet echt leesbaar dus, zeker niet - als het alweer een paar weken geleden is dat je voor het - laatst naar die source gekeken hebt. - - De basisprincipes zijn nu hopelijk duidelijk, de volgende - keer zal ik hier verder op doorgaan. - - Stefan Boer diff --git a/sunrise_special/6/MSX View.md b/sunrise_special/6/MSX View.md deleted file mode 100644 index c2f9961..0000000 --- a/sunrise_special/6/MSX View.md +++ /dev/null @@ -1,102 +0,0 @@ - M S X - V I E W - - - Iedereen kent wel Halos. Het operating system van HAL - laboratories dat er goed uitziet maar slecht werkt en - eigenlijk onwerkbaar is. Mensen die het versienummer wel - eens hebben bekeken weten dat de Halos die idereen heeft - versie 0.0.4 is van de echte Halos die in Japan te koop is. - De uiteindelijke Halos is weer de voorloper van MSX-View. De - twee zijn danook bijna identiek. (MSX-View is voor tR en - werkt onder DOS2, dus met shells e.d.) - - MSX-View is een programma dat het mogelijk maakt om met - windows te werken en nog veel meer. MSX-View zelf bestaat - enkel en alleen uit een kernel die verborgen zit in de - memorymapper. Zijn 300 a 400 functies zijn aan te roepen via - RST 8 DW [functienr]. Gelukkig zijn er ook zgn. applicaties - voor MSX-View zoals VSHELL (een DOS-Shell), ViewTED (een - tekst editor), ViewDRAW (een DTP programma) etc. Daarover - wil ik eigenlijk niet gaan schrijven, en dit is dus bedoeld - voor programmeurs. - - - A A N S T U R E N V A N M S X - V I E W - - Oftewel het zelf schrijven van applicaties en .DA files. - (Overlay programma's die tijdens de uitvoering van een - applicatie kunnen worden ingeladen, denk aan een calculator, - notitieboekje, etc.) Toevallig ben ik ooit eens tegen een - MSX-FAN opgelopen met daarop MSX-View library's voor MSX-C. - Door de informatie die hier in staat is het mogelijk zelf - applicaties te schrijven is zowel C als assembly, wat je - maar wilt. Ik heb mijn eerste applicatie al af. - - Iedere C of ML programmeur moet volgens mij applicaties - kunnen schrijven. Zo moeilijk is het niet. En hoe meer - applicaties hoe meer ondersteuning MSX-View krijgt en dat is - ook belangrijk. - - - W A A R O M N I E T I E T S A N D E R S - - Ik hoor iedereen nu al weer roepen: MSX-View is Japans, daar - heb je niets aan, het is veel te ingewikkeld en te traag en - ik schrijf zelf wel een goed windows programma. Maar neem - maar van mij aan dat dit het beste windows programma is dat - ooit op de MSX zal verschijnen. MSX-View zelf is alleen een - kernel en hoewel er standaard messages inzitten - (bijvoorbeeld copy of quit, maar dan in het Japans) hoef je - die natuurlijk niet te gebruiken. En anders koop je toch - gewoon de MSX-View patch van MGF, dan zijn die standaard - messages ook vertaald. Wees dus niet eigenwijs en gebruik - MSX-View. Het is echt waanzinnig goed. - - - F U N C T I E V O O R B E E L D E N - - Een paar voorbeeldfuncties met uitleg: - - GetEvent - Kijkt welke keuze is gemaakt/toets is - ingedrukt,etc. - FrontWin - Zet het huidige window voor alle andere - windows. - DispAllCntl - Drukt alle controls af (bv. schuif, - switch, checkmark) - OpenMenu - Opent pull-down menu systeem (gedefenieerd - door eigen programma) - InitGraf - Initializeert de MSX-View GrafPack - FillPai - Drukt een stuk cirkel af, gevuld met een - patroon - GetDiskInfo - Haal informatie op over een diskdrive(of - disk die erin zit) - GetSin - Haal een waarde uit de sinus-tabel - FilePack(...) - Laad/Save een (gedeelte van een) file - (Er verschijnt een keuzemenu waar - directories,drives en files kunen worden - doorlopen, een naam kan worden ingegeven - en vervolgens OK of ABORT kan worden - gekozen.) - ErrMessage - Plaats een error-window in het midden van - het scherm met een message, een of - meerdere buttons eronder en evt. en teken - ernaast (disk, uitroepteken...) keert - terug met de gekozen button in A - - MSX-View werkt ook met gestandariseerde dataopslag. De - GetEvent levert het event bijvoorbeeld in een door jou - gekozen eventbuffer. Het systeem is door zijn jarenlange - ontwikkeling geperfectioneerd tot in de kleinste details en - dat blijkt uit alles. - - - Z E L F A P P L I C A T I O N S M A K E N ? - - Als je interesse hebt in hoe dit alles in de praktijk in - zijn werk gaat, of je hebt belangstelling voor de library's - en programma's waarmee dit alles moet worden bewerkstelligd - dan hoef je alleen maar even contact op te nemen met mij via - post, telefoon of echomail, uploads/downloads alleen via - Piramide BBS. - - Jan van Valburg diff --git a/sunrise_special/6/MSX2 Blink besturing.md b/sunrise_special/6/MSX2 Blink besturing.md deleted file mode 100644 index 892d913..0000000 --- a/sunrise_special/6/MSX2 Blink besturing.md +++ /dev/null @@ -1,304 +0,0 @@ - M S X 2 B L I N K B E S T U R I N G - - - Een van de nieuwe mogelijkheden van de MSX2 video chip is de - zogenaamde BLINK. Voor screen 0 is dit een extra - mogelijkheid om delen van het scherm van een 3e en/of 4e - kleur te voorzien. Ook in andere screen modes is de blink - uitstekend te gebruiken. Maar in dit artikel beperk ik me - tot screen 0 mode 80. - - In de VDP cursus #7 is hier ook al het een en ander - geschreven. In dit artikel zal ik proberen de mogelijkheden, - en vooral het gebruik van de blink te beschrijven, met -in - assembly geschreven- routines. - - - B A S I S A D R E S - - Elke positie op het scherm kan in de blink mode worden - gezet. Voor elke positie is 1 bit gereserveerd. Als deze - hoog is, is de blink geactiveerd. Deze informatie wordt - bewaard in de Blink tabel. Het start adres van deze tabel - wordt gespecifeerd door het zetten van de 8 hoge bits in - register #3 en #10 (A9-A16). De 9 laagste bits zijn altijd - "1" waardoor de tabel altijd om de 512 bytes ligt. Een blink - tabel is 512 bytes lang, dus kunnen er 512*8 posities op het - scherm worden aangezet (1 bit per karakter). - - MSB b7 b6 b5 b4 b3 b2 b1 b0 LSB - r#3 A13 A12 A11 A10 A9 1 1 1 - r#10 0 0 0 0 0 A16 A15 A14 - - Formules: - VRAM adr = r#3 and &hF8 * 64 - r#3 = VRAM adr / 64 and &h00F8 or &h07 - - Hierbij laat ik r#10 gewoon nul, omdat in de praktijk de - blink tabel nooit zo hoog in het VRAM zal worden gezet. - - Stel we willen de Blink tabel laten beginnen op VRAM adres - &h0E00, dan zullen de register als volgt moeten worden gezet: - - r#3 &h3F (&h0E00/64 or 7) - r#10 &h00 - - standaard zijn deze registers gevuld met de volgende - waarden: - r#3 &h27 (VRAM adr: &h0800) - r#10 &h00 - - In Assembly zal een dergelijke berekening voor het basis - adres er als volgt - uitzien: - - ; Set Blink Base address. - ; In: H(L), VRAM adr. L, not necessary. - BLNBAD: XOR A ; Hoogste bits:0 - LD (BLN_BA),A - LD A,H - AND &HFE - LD (BLN_BA+1),A - RLCA - RLCA - AND &HF8 - OR &H07 - DI - OUT (&H99),A - LD A,3 OR &H80 ; r#3 - OUT (&H99),A - EI - RET - BLN_BA DW &H0800 ; (standaard) - - Omdat het adres altijd in stappen van 512 bytes gaan, zullen - de 8 laagste bits in ieder geval "0" zijn. Vandaar dat de - routine begind met het nul maken van de laagste bits. - Het VRAM adres wordt bewaard, zodat deze later is te - gebruiken bij het beschrijven van deze tabel. - - - K L E U R E N T I J D S D U U R - - De kleuren van de blink worden gezet in r#7. Waarbij de - hoogste 4 bits de kleur van de karakters is, en de laatste 4 - bits de kleur van de blink achtergrond. - - MSB b7 b6 b5 b4 b3 b2 b1 b0 LSB - r#7 FC3 FC2 FC1 FC0 BC3 BC2 BC1 BC0 - - N.B. FC0-FC3: Foreground Colour - BC0-BC3: Background Colour - - voorbeeld: - We willen de karakters waar de blink mode aan staat, geel - maken, en de achtergrond daarvan rood. Dan wordt r#7 als - volgt: - r#7, &hA6 (A=geel, 6=rood) - - Voor de tijd dat de blink mode aan/uit staat, moeten we r#12 - gebruiken. De 4 hoogste bits bevatten de tijd dat de kleuren - (r#3) worden geactiveerd, de 4 laagste is de tijd dat de - originele karakter kleuren weer worden geactiveerd. - - MSB b7 b6 b5 b4 b3 b2 b1 b0 LSB - r#12 BC3 BC2 BC1 BC0 CC3 CC2 CC1 CC0 - - N.B. BC0-BC3: Blink Colour - CC0-CC3: Charakter Colour - - De tijd wordt aangegeven in "vertical scans", dus elke 1/50 - (of 1/60) seconde. - - Met deze 4 genoemde registers is de initialisatie van de - blink verklaard. Alles wat we nu nog moeten doen is - daadwerkelijk de scherm posities aan of uit zetten. - - - S C H E R M P O S I T I E - - De posities van de blink worden als volg berekend: - (uitgaand van een width 80 scherm) - - [basis adres] + (Yx10) + (X/8) - - Omdat er per bit wordt gerekend, wordt de X gedeeld door 8 - (8 bits). Omdat er maximaal 80 karakters op een scherm - kunnen, worden er dus 10 bytes gebruikt voor een Y lijn - (80/8). - - Voordat we de blink gaan gebruiken, doen we er goed aan om - eerst de hele blink tabel leeg te maken. Een soortgelijke - routine: - - ; Clear Blink table. - BLNCLR: LD HL,(BLN_BA) ; basis adres - LD C,0 ; laagste 64k. - LD DE,512 ; totaal aantal bytes - XOR A ; vul met nul - JP FILVRM ; een "Vul VRAM" routine - - De "FILVRM" routine in dit voorbeeld heeft de volgende - data nodig: - HL/C, VRAM adres C bepaalt welk VRAM blok (64k.) - DE, lengte - A, vuldata - - Natuurlijk kunt u uw eigen routine ook gebruiken. - - Nu komt eigenlijk het moeilijkste, een routine maken die een - blink positie aan of uit zet. Hierbij moet het VRAM adres, - en het start bit worden berekend. Dit laatste is - noodzakelijk omdat immers per bit wordt gerekend. Ook is het - belangrijk, dat de bits die al aan/uit stonden onveranderd - te laten! - - De volgende routine zal het VRAM start adres berekenen: - - ; Calculate Blink VRAM adr. - ; In: H, pos-X. L, pos-Y - ; Out: HL, VRAM adr. - C_BLAD: LD A,H - RRCA ; X/8 - RRCA - RRCA - AND &HF8 - LD H,A - LD A,L ; Yx10 (Yx2 + Yx8) - RLCA - AND &H3F - LD L,A ; L=Yx2 - RLCA ; Yx4 (+Yx4 = Yx8) - RLCA - ADD A,H ; (Ax8) + (Ax2) - ADD A,L ; + X - LD L,A - LD A,(BLN_BA+1) ; basis adres - LD H,A - LD (BLN_AD),HL ; bewaar VRAM adres - RET - - BLN_AD DW &H0800 - - Deze routine is uiters snel qua berekening, maar heeft 1 - beperking, dat er maar 256 VRAM adressen (2048 posities) - kunnen worden berekent Hierdoor is het start adres bekend, - nu nog het start bit. - - Door gebruik te gaan maken van een vermenig vuldigins - routine, is dit wel mogelijk maar dat gaat dan wel ten koste - van de snelheid. Voor dergelijke rekenroutine verwijs ik u - naar de Z80 REKEN cursus van Alex van der Wal (special #5). - Een blink adres berekening routine gebruik makend van - vermenig vuldiging: - - ; calc Blink VRAM-adres. - ; In: HL, XXYY (blink pos.) - C_BLAD: LD A,H - AND &HF8 - RRCA - RRCA - RRCA ; /8 - PUSH AF - LD A,L ; Y*10 - LD DE,10 - CALL HL=ADE ; Uit: HL= A x DE - POP AF - LD C,A - LD B,0 - ADD HL,BC - LD BC,(BLN_BA) - ADD HL,BC - LD (BLN_AD),HL - RET - - A bevat nu een bit waarmee moet worden gestart. Stel nu dat - we als X positie 5 nemen. Het start bit (in reg. A) zal dan - als volgt zijn: (uitgaand dat X de waarde 0-79 kan hebben) - - A, &b00000100 ; 5e bit van links is hoog. - - Met deze start gegevens kunnen we nu een scherm positie - voorzien van de blink mode. De volgende routine zal een - (aantal) posities aan (kunnen) zetten: - - ; Set blink position ON. - ; In: H, pos-X. L, pos-Y. B, total positions - BLNON: PUSH BC - LD A,H - PUSH AF - CALL C_BLAD ; VRAM adres - POP AF - CALL C_STBT ; start bit - POP BC - LD E,A - BLON.1 LD C,0 ; laagste 64k. - CALL SR_VRM ; Zet VDP in lees mode. - IN A,(&H98) ; Lees oude blink bits. - PUSH AF - CALL SW_VRM ; Zet VDP in schrijf mode. - POP AF - BLON.0 OR E - RRC E ; Schuif bit - JR NC,BLON.2 ; Laagste bit gehad? - OUT (&H98),A ; ja, schrijf Blink - INC HL : volgende 8 posities. - DJNZ BNON.1 - RET - BLON.2 DJNZ BLON.0 - OUT (&H98),A - RET - - De routines "SR_VRM" en "SW_VRM" zorgen er voor dat de VDP - in lees of schrijf mode wordt gezet. Natuurlijk kunt u hier - ook uw eigen routines gebruiken. - De "OR E" instructie zorgt ervoor dat de desbetrefende bits - worden gezet, zodra het laatste bit gedaan is (b0), wordt de - volgende VRAM positie (8 bits) gebruikt. - - Een routine die of een (of meer) blink positie(s) zet: - - ; Reset Blink position. - ; In: H, pos-X. L, pos-Y. B, total pos. - BLNOFF: PUSH BC - LD A,H - PUSH AF - CALL C_BLAD ; VRAM adres - POP AF - CALL C_STBT ; start bit - POP BC - CPL ; draai bits om - LD E,A - BLOF.1 LD C,0 ; laagste 64k. - CALL SR_VRM ; Zet VDP in lees mode. - IN A,(&H98) ; Lees oude blink bits. - PUSH AF - CALL SW_VRM ; Zet VDP in schrijf mode. - POP AF - BLOF.0 AND E ; zet 1 bit uit. - RRC E ; Schuif bit - JR C,BLOF.2 ; Laagste bit gehad? - OUT (&H98),A ; ja, schrijf Blink - INC HL : volgende 8 posities. - DJNZ BNOF.1 - RET - BLOF.2 DJNZ BLOF.0 - OUT (&H98),A - RET - - Deze routine is feitelijk het zelfe als "BLNON", maar nu - wordt de instructie "AND E" gebruikt om de bits uit te - zetten. - Met deze 2 laatst genoemde routines is het natuurlijk heel - makelijk om een routine te maken die een Blok aan of uit - zet, waarbij bijvoorbeeld "B" het aantal X posities is en - "C" het aantal Y posities. Hierbij kan gebruik worden - gemaakt van het VRAM adres wat opgeslagen staat in "BLN_AD". - Nu hoeft het adres, en het start bit maar 1 keer worden - berekend. Het VRAM adres van de volgende Y posities ligt 10 - hoger. - - Met deze routines en uitleg moet het mogelijkzijn om de - Blink voledig te benutten in screen 0. - - R�man van der Meulen diff --git a/sunrise_special/6/Memman TSR Development Kit.md b/sunrise_special/6/Memman TSR Development Kit.md deleted file mode 100644 index cbfa6bb..0000000 --- a/sunrise_special/6/Memman TSR Development Kit.md +++ /dev/null @@ -1,81 +0,0 @@ - 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: MCCM's lezersservice - - - 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 diff --git a/sunrise_special/6/Memman in theorie en praktijk.md b/sunrise_special/6/Memman in theorie en praktijk.md deleted file mode 100644 index 281da30..0000000 --- a/sunrise_special/6/Memman in theorie en praktijk.md +++ /dev/null @@ -1,241 +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 diff --git a/sunrise_special/6/Memory Mapper.md b/sunrise_special/6/Memory Mapper.md deleted file mode 100644 index 1ac0b49..0000000 --- a/sunrise_special/6/Memory Mapper.md +++ /dev/null @@ -1,272 +0,0 @@ - M E M O R Y M A P P E R - - - De Z80 kan maar 64 kB geheugen tegelijk adresseren. Om toch - meer dan 64 kB RAM te kunnen gebruiken is de memory mapper - bedacht. De memory mapper behoort niet tot de MSX2- - standaard, en daarom heeft de MSX2 geen standaard - aanstuurroutines voor de memorymapper. - - Vanaf MSX2+ behoort de mapper wel tot de standaard en daarom - zitten er in DOS2 (dat ongeveer gelijktijdig met MSX2+ werd - gelanceerd) wel mapperroutines. - - Veel software die de mapper gebruikt werkt niet onder DOS2, - dat komt door een verkeerd gebruik van de mapper. In dit - artikel zal ik uitleggen hoe de mapper werkt, en hoe je hem - zo kunt aansturen dat het zowel onder DOS1 als onder DOS2 - probleemloos werkt. - - - W E R K I N G - - Het geheugen in een mapper wordt opgedeeld in blokken van 16 - kB, die mapperpages of mappersegmenten worden genoemd. - Aangezien het woord page verwarrend is zal ik hier verder - het woord segment aanhouden. - - Deze segmenten worden oplopend genummerd, te beginnen bij 0. - Een mapper van 256 kB heeft 16 segmenten die genummerd zijn - van 0 tot en met 15. - - De 64 kB adresbereik wordt opgedeeld in vier pages van 16 kB - elk. Op elke page kan een memory mapper worden geschakeld - door gebruik te maken van de routine ENASLT op adres &H24. - Vervolgens kan een segment worden geselecteerd door de - juiste waarde naar de corresponderende out-poort te sturen. - Een overzicht: - - page 0 #0000-#3FFF mapperpoort #FC - page 1 #4000-#7FFF mapperpoort #FD - page 2 #8000-#BFFF mapperpoort #FE - page 3 #C000-#FFFF mapperpoort #FF - - Zo kun je bijvoorbeeld segment 7 selecteren op adres #8000 - met de volgende instructies: - - LD A,7 - OUT (#FE),A - - Het is op zich heel eenvoudig om met verschillende mappers - te werken, gewoon met ENASLT het slot van de gewenste mapper - selecteren op de gewenste page. - - Je mag mapperpoort #FF niet veranderen omdat zich daar het - systeemgebied bevindt. Dit zal altijd segment 0 zijn van de - mapper waarmee de computer opstart. Dit zal bij een MSX2 of - MSX2+ de grootste mapper zijn en bij de turbo R de interne - mapper. Dit omdat de interne mapper van de turbo R sneller - is dan een externe mapper. De communicatie van de R800 met - de cartridgesloten gaat namelijk in een langzamere snelheid. - - Bij het opstarten worden de volgende segmenten geselecteerd: - - page 0 mapperpoort #FC segment 3 - page 1 mapperpoort #FD segment 2 - page 2 mapperpoort #FE segment 1 - page 3 mapperpoort #FF segment 0 - - Wat mij betreft mag je hiervan uitgaan omdat alle bekende - MSX computers het zo doen. Officieel ligt echter alleen vast - dat het systeemgebied zich in segment 0 begint. - - - W R I T E O N L Y ! - - De mapperpoorten zijn officieel write only, wat uiteraard - betekent dat je ze alleen mag beschrijven en dat lezen geen - zin heeft. Toch gaat het lezen meestal goed en het wordt in - programma's die voor DOS1 zijn geschreven dan ook heel veel - gedaan. - - Hierdoor ontstaan twee problemen: - - 1) de software werkt niet meer onder DOS2 - 2) de software werkt niet goed op een MSX2+ of turbo R met - een externe mapper die groter is dan 512 kB - - Ik zal deze problemen hieronder bespreken. - - - D O S 2 - - Ze weten bij ASCII natuurlijk heel goed dat de mapperpoorten - niet mogen worden gelezen en dus wordt dezelfde methode - gehanteerd als voor het 'lezen' van VDP-registers in BASIC, - telkens als er een waarde naar een mapperpoort wordt - gestuurd wordt deze waarde op een vast adres bewaard. De - routine die 'leest' welk segment er voor een bepaalde page - is geselecteerd leest dus gewoon dat RAM adres uit! - - Deze adressen liggen vast en zijn: - - page 0 mapperpoort #FC #F2C7 - page 1 mapperpoort #FD #F2C8 - page 2 mapperpoort #FE #F2C9 - page 3 mapperpoort #FF #F2CA - - Stel je wilt iets laden in segment 7. Je doet dus OUT - (#FE),7 en je roept een BDOS routine aan. Nu komt DOS2 in - actie. Die zet voor de zekerheid de mapper nog even "goed", - hij doet daarvoor LD A,(#F2C9) en OUT (#FE),A. De data komt - dus in een ander segment terecht dan de bedoeling was! - - Dit is de reden waarom programma's die de mapper - rechtstreeks aansturen niet werken onder MSX-DOS 2. De - oplossing voor dit probleem heet MAP. Dit programmaatje werd - gemaakt door Henrik Gilvad uit Denemarken. Het is eigenlijk - heel simpel, hij zoekt gewoon in de DOS2 routines naar de - instructie LD A,(#F2C9) en hij maakt daar IN A,(#FE) van. - Hetzelfde gebeurt met #F2CA en #F2C8, met MAP2, een - uitgebreidere versie, wordt ook #F2C7 'gepatcht'. - - Dit is een paardemiddel dat alleen gebruikt mag worden om te - proberen bestaande software toch onder DOS2 te laten lopen, - de mapperpoorten worden nu immers toch weer gelezen! - - Dat dat niet alleen in de theorie niet mag maar ook niet in - de praktijk blijkt uit het volgende probleem. - - - E X T E R N E M A P P E R - - Bij een externe mapper gaat het lezen van de mapperpoorten - op de Japanse MSX2+ en MSX turbo R computers niet goed! De 3 - hoogste bits zijn namelijk altijd "1"! Dit is de reden - waarom Digital KC in de advertentie voor zijn megamappers - zegt dat ze niet goed werken op MSX2+ en MSX turbo R. - - Omdat het alleen de bovenste 3 bits zijn gaat het bij een - mapper tot 512 kB wel goed, maar dit praktijkgeval bewijst - dat je de mapperpoorten dus echt niet mag lezen! - - - D E O P L O S S I N G - - Op Sunrise Magazine #12 schreef ik nog dat MAP de oplossing - was, maar na een brief van Henrik Gilvad weet ik wel beter. - De enige goede oplossing is om net als DOS2 de waardes die - je naar de mapperpoorten schrijft te bewaren zodat je ze - niet hoeft te lezen. Als je dat onder DOS2 op dezelfde - adressen doet als waar DOS2 dat doet, dan is het meteen - compatible met DOS2 en zal je programma daaronder werken. - Onder DOS1 kun je die adressen beter niet gebruiken omdat ze - zich bevinden in het systeemgebied van de BDOS. Onder DOS1 - gebruik je dus andere adressen dan onder DOS2 om de waardes - op te slaan. - - Onderstaande source bevat routines ReadFE, WriteFE, ReadFC, - etc. Gebruik deze routines voortaan in plaats van OUT - (#FE),A respectievelijk IN A,(#FE). Het is slechts een klein - beetje langzamer en de voordelen zijn duidelijk: het werkt - onder alle omstandigheden op alle computers! - - - ; MAPPER.GEN - ; Standaard mapperroutines - ; Werken onder DOS1 & DOS2 - ; Compatible met DOS2 - ; Voor eerste gebruik InitMapRouts aanroepen - ; Niet rechtstreeks de mapper aansturen, alles - ; via deze routines doen!!! - - ; Door Stefan Boer - ; Sunrise Special #6 - ; (c) Stichting Sunrise 1994 - - ; Init mapper routines - ; Aanroepen voor gebruik van Read/Write routines! - - InitMapRouts: LD A,(#F313) - AND A - RET Z ; DOS1 - - LD HL,#F2C7 ; DOS2 - LD (ReadFC+1),HL - LD (WriteFC+1),HL - - INC HL - LD (ReadFD+1),HL - LD (WriteFD+1),HL - - INC HL - LD (ReadFE+1),HL - LD (WriteFE+1),HL - - INC HL - LD (ReadFF+1),HL - RET - - ; ruimte voor opslag onder DOS1 - - StoreFF: DB 0 - StoreFE: DB 1 - StoreFD: DB 2 - StoreFC: DB 3 - - - ; Read - ; In : - - ; Uit: A = segmentnummer - - ReadFC: LD A,(StoreFC) - RET - - ReadFD: LD A,(StoreFD) - RET - - ReadFE: LD A,(StoreFE) - RET - - ReadFF: LD A,(StoreFF) - RET - - ; Write - ; In : A = segmentnummer - ; Uit: - - ; Er is net als bij DOS2 geen WriteFF want die mag je - ; niet veranderen! - - WriteFC: LD (StoreFC),A - OUT (#FC),A - RET - - WriteFD: LD (StoreFD),A - OUT (#FD),A - RET - - WriteFE: LD (StoreFE),A - OUT (#FE),A - RET - - - Vergeet niet eerst even InitMapRouts aan te roepen, die - zorgt ervoor dat onder DOS2 de gebruikte adressen worden - gewijzigd in de adressen die DOS2 zelf ook gebruikt. Let er - verder op dat de mapper nergens in je programma meer - rechtstreeks wordt aangestuurd, ook niet bijvoorbeeld door - de MoonBlaster replayer. Ik zal nog aan Remco vragen of hij - een nieuwe versie van de replayer released waarin deze - mapperroutines zijn ingebouwd, maar je kunt dit ook - eenvoudig zelf aanpassen. - - - T E N S L O T T E - - Wees nu niet eigenwijs en gebruik deze routines gewoon, ook - als je zelf geen DOS2 hebt. Steeds meer MSX'ers hebben een - harddisk en vaak zal het doorslaggevend zijn bij de - beslissing om je produkt al dan niet te kopen of het op - harddisk kan worden ge�nstalleerd. E�n van de voorwaarden - daarvoor is dat het onder DOS2 werkt. Bovendien zal je - programma op een MSX2+ of turbo R met externe mapper van 1 - MB of meer niet werken als je dat geheugen ook daadwerkelijk - gaat gebruiken. - - Als je in het systeemgebied van DOS2 gaat rondneuzen zul je - overigens zien dat DOS2 exact dezelfde routines gebruikt om - de mapper aan te sturen! Je kunt deze routines echter niet - handig gebruiken omdat ze niet op een vast adres staan. Je - kunt MAPPER.GEN op de disk vinden. - - Stefan Boer diff --git a/sunrise_special/6/SCC geluid via stereo pak.md b/sunrise_special/6/SCC geluid via stereo pak.md deleted file mode 100644 index a7583ef..0000000 --- a/sunrise_special/6/SCC geluid via stereo pak.md +++ /dev/null @@ -1,28 +0,0 @@ - S C C G E L U I D V I A S T E R E O P A K - - - Op een vorige Special stond een tekst over de STEREO SCC, om - het geluid (SCC-PSG) gescheiden weer te geven. Hiervoor - moest u een kleine ingreep doen in uw SCC-cartridge. In deze - tekst wordt uitgelegd hoe u het SCC- en het PSG-signaal door - uw versterker kunt weergeven d.m.v. de stereo FM-PAK! - - Plaats in een van de cartridgesloten uw SCC-cartridge en in - de andere uw stereo FM-PAK. Sluit nu de FM-PAK aan met de 2 - bijgeleverde kabels. Hoe dit moet staat in de handleiding - vermeld. - - Laad nu een SCC-demo of start bijvoorbeeld Solid Snake of - SD-Snatcher op. U zult merken dat het SCC geluid nu prima en - helder door uw stereo-installatie wordt weergegeven. Het - geluid wordt uiteraard nu ook door uw monitor afgespeeld. - Bezitters van alleen een monitor (bij hen ontbreekt dus een - stereo-installatie of er zit geen AUX-ingang op), hoeven - uiteraard deze aansluiting niet te maken. - - Hopelijk kunt u op deze manier beter en mooier van uw SCC - geluid genieten! Zeker als u SD-Snatcher speelt met de BASS - voluit. De ontploffingen van de vijanden klinken dan pas - echt "ECHT"! Succes! - - Haiko de Boer diff --git a/sunrise_special/6/Sprites in de praktijk.md b/sunrise_special/6/Sprites in de praktijk.md deleted file mode 100644 index 845bdcb..0000000 --- a/sunrise_special/6/Sprites in de praktijk.md +++ /dev/null @@ -1,156 +0,0 @@ - S P R I T E S I N D E P R A K T I J K ( 2 ) - - - In de vorige keer heb ik het gehad over het initialiseren - van de sprites en het daad werkelijk plaatsen van een - sprite. In deze aflevering wil ik het sprite verhaal - afsluiten met de kleurcodes voor sprite mode 2 (MSX2 en - hoger) en de sprite botsing detectie (beide modes). - - - S P R I T E K L E U R E N I N M O D E 2 - - In mode 1 wordt het vierde byte in de atribute van een layer - gebruikt om de kleur van een sprite layer te definieren. - Daardoor is er slechts 1 kleur in een sprite mogelijk. De - tweede sprite mode lost dit anders op door hier een aparte - kleur tabel te gebruiken. Hierdoor is het mogelijk om elke Y - lijn van een sprite layer een andere kleur te geven. Door - somige bits te zetten, zijn zelfs 3 kleuren op 1 lijn - mogelijk. Door dat er een kleur tabel wordt gebruikt wordt - het vierde byte in de atribute tabel verwaarloosd. Let op - dat deze byte nog wel aanwezig is, waardoor een sprite layer - atribute nog steed 4 bytes gebruikt. - - Het basis adres van de kleur tabel wordt opgegeven in r#5 en - r#11 zoals in deel in is beschreven. Als deze registers - worden beschreven wordt automatisch het adres van de - atribute tabel gelijk aan de kleur tabel + 512 (&h0200). - - Voor iedere layer zijn 16 bytes gereserveerd voor de kleur. - Ook als er gebruik wordt gemaakt van 8x8 sprites! Als er - 16x16 sprites vergroot worden gebruikt, worden er 2 Y lijnen - met de zelfde kleur gevuld. Een dergelijke kleuren tabel is - dus: 16 x 32 = 512 bytes lang. - - - E X T R A C O D E S - - Samen met de kleur waarden kunnen er ook nog andere bits - worden gezet, die speciale effecten aan de sprite layer - geven. Een kleur byte bevat het volgende: - - MSB b7 b6 b5 b4 b3 b2 b1 b0 LSB - EC CC IC 0 - Kleur code - - - EC: Heeft de zelfde functie als het EC bit in de - atribute tabel van sprite mode 1. Als deze - "1" is wordt de sprite lijn 32 pixels naar - links geschoven. (zie verdere uitleg, deel - 1) - CC: Het zogenaamde prioriteit bit. Als dit "1" - is krijgt de sprite lijn de zelfde - prioriteit als de voorligende sprite. - Hierbij worden de kleuren van beide sprite - ge 'OR'ed. Dit zorgt echter niet voor een - sprite botsing. - IC: Als deze "1" is, wordt een sprite botsing - genegeerd. - - Van elke Y lijn van een sprite kan er een andere kleur en - code worden opgegeven. - - voorbeeld van het prioriteit bit: - (met prioriteit wordt bedoeld dat een layer met een lager - nummer voor een layer met een hoger nummer wordt geplaatst) - - Als de kleur van sprite layer 0 (hoogste prioriteit) kleur 8 - is, en van sprite layer 1 kleur 4. Bij sprite layer 1 wordt - het CC bit gezet. Hierdoor krijgt layer 1 de zelfde - prioriteit als layer 0. De kleuren worden nu ge'OR'ed - waardoor er kleur 12 ontstaat waar de patroon bits "1" zijn. - Hierdoor heeft deze sprite lijn dus 3 kleuren namelijk de - kleuren 4, 8 en 12. - Het start adres van de kleuren tabel: (basic adr: &h7400) - layer 0: &h7400 (CC=0), kleur 4 - layer 1: &h7410 (CC=1), kleur 12 - - - S P R I T E C O N F L I C T - - Hiermee wordt het 'botsen' van sprites bedoeld. In mode 1 - kan alleen worden nagegaan of er een sprite conflict is - opgetreden, terijl in mode 2 ook nog de X en Y coordinaten - van de botsen kan worden opgevraagd. - - Een conflict onstaat als twee sprites elkaar raken. Hierbij - wordt wel gekeken of beide patroon bits van de sprite "1" - zijn en de kleur hiervan niet transparant is. Dus als beide - sprites ook werkelijk geconstrueerd zijn. Het volgende - voorbeeld maakt dit duidelijker: - - sprite 1: XXXX---- sprite 2: //////// - XXXX---- //////// - (8 x 8) XXXX---- //////// - XXXX---- ////YYYY - -------- ////YYYY - -------- ////YYYY - -------- //////// - -------- //////// - - Als deze sprite als volgt over elkaar worden geplaatst, - volgt er een conflict: - XXXX---- - //XXXX---- - //XXXX---- - //XXXX---- - //XXZZYY - ////YYYY - ////YYYY - ////YYYY - //////// - //////// - - - Als twee sprites botsen, dan wordt in status reg. s#0 bit 5 - gezet. Als er in mode 2 wordt gewerkt kunnen de de X - coordinaten worden gahaald uit s#3/s#4, en de Y coordinaten - uit s#5/s#6. Om nu uit te zoeken om welke sprites het gaat, - zou je zelf een routine kunnen maken die de coordinaten van - de sprites met elkaar gaat vergelijken. - - MSB b7 b6 b5 b4 b3 b2 b1 b0 LSB - ---+---+---+---+---+---+---+--- - s#3 X7 X6 X5 X4 X3 X2 X1 X0 - s#4 1 1 1 1 1 1 1 X8 - s#5 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 - s#6 1 1 1 1 1 1 Y9 Y8 - - - R E S T N O G . . . - - ...de informatie over de 5e/9e sprite op een gelijke Y as. - In mode 1 kunnen er 4 sprites en in mode 2 kunnen er 8 - sprites op een dezelfde beeldlijn worden vertoond. Als er - meer sprites worden neergezet wordt bit 6 van s#0 gezet, en - bevatten b0-b4 het 5e/9e sprite nummer. - - Een 5e/9e (en hoger) sprite wordt dan niet weergegeven. De - meeste software programmeurs (voor al in spellen) hebben dit - opgelost door het alom bekende 'knipper' effect. Hierdoor - wordt bijvoorbeel de 5e/9e sprite verwisseld met sprite 1 - waardoor deze snel om de beurt worden weergegeven. Op deze - manier zijn de sprite toch allemaal zichtbaar. - - - Als het goed is, is op deze special een assembly file - aanwezig met de naam: - "SPRITES .asc" - - Deze bevat diverse routines om de sprite basis adresen te - zetten en/of te berekenen, plus nog enkele handige routines. - In die routines worden ook subroutines gebruikt, die u zelf - kunt bijvoegen (o.a. reken routines). - - Veel spritefun! - R�man van der Meulen diff --git a/sunrise_special/6/Subdirs onder DOS1.md b/sunrise_special/6/Subdirs onder DOS1.md deleted file mode 100644 index 00c3cb3..0000000 --- a/sunrise_special/6/Subdirs onder DOS1.md +++ /dev/null @@ -1,156 +0,0 @@ - S U B D I R S O N D E R D O S 1 - - - Tot nu toe was het onmogelijk om onder DOS1 in - subdirectory's te kijken, laat staan om ze te gebruiken. - Maar nu zijn er Japanse programmaatjes die dit wel mogelijk - maken. Het systeem is geheel compatible met MSX-DOS2 en - MS-DOS, dus het is echt ideaal. - - - W E R K I N G - - Eerst moet je de disk die je ermee wilt gebruiken een naam - geven. Dit gebeurt met LABEL.COM. Je typt gewoon achter - LABEL de naam in, en de disk wordt zo genoemd. Ik weet niet - precies waarom dat nodig is, maar volgens mij wordt er dan - een tabelletje aangemaakt, waarin de verderop besproken - subdirectory utils de benodigde info dumpen. - - Als je LABEL.COM niet eerst gebruikt, weigeren de - DIR-utility's om te werken. Je krijgt dan een Japanse - foutmelding - die ik eerst niet helemaal snapte ("No volume - table"). - - - C H D I R . C O M - - CHDIR staat uiteraard voor CHange DIRectory, en je kunt er - dus mee van directory veranderen. Als je geen directory - achter CHDIR opgeeft, wordt de huidige directory afgebeeld. - Dat is wel handig, want die krijg je niet te zien bij het - commando DIR. Gelukkig neemt DIR de subdirectory's wel al - mee in het overzicht van de files, met erachter vermeld - "". - - - M K D I R . C O M - - Dit staat natuurlijk voor MaKe DIRectory, en hiermee kun je - dus de directory's aanmaken. Ook hier moet je weer gewoon - achter MKDIR de aan te maken directory opgeven. - - - R M D I R . C O M - - En tenslotte nog ReMove DIRectory, juist ja, het verwijderen - van - lege - subdirectory's. - - - H O E K A N D A T N O U ? - - Als je even goed nadenkt, is het natuurlijk onmogelijk om al - deze DIR-utils te gebruiken. Als je immers eenmaal in een - andere directory zit, kun je de utility's zelf niet meer - gebruiken, omdat die uiteraard in de root-dir - de stam - - staan. En je zou dan dus moeten resetten om terug te keren. - - Hiervoor heeft de Japanse programmeur echter een oplossing - bedacht: in SETDIR.SYS kun je de bestanden plaatsen die in - elke directory komen. Uiteraard dienen tenminste de volgende - files erin te staan: - - COMMAND.COM - MSXDOS.SYS - CHDIR.COM - MKDIR.COM - RMDIR.COM - SETDIR.SYS - - Maar het is natuurlijk altijd handig om andere utility's, - zoals TED erin te zetten. - - Er zijn echter nog meer handige programmaatjes die bij deze - verzameling horen: - - - R A M D I S K . C O M - - Dit is natuurlijk een RAMdisk programma voor DOS1. Het is - best wel handig, omdat het niet terug naar BASIC gaat, en - toch wel dezelfde kwaliteiten heeft als de Nederlandse - RAMdisk programma's - behalve als je natuurlijk toch al de - hele MemMan gebruikt, want dan is RAMdisk 4.00 het beste. - - Bij RAMDISK.COM kun je niet de hoeveelheid te gebruiken - geheugen opgeven, maar wel welk geheugen gebruikt moet - worden: - - /V : alle VRAM - /M : alle (main) RAM - Hierachter kan eventueel het slotnummer opgegeven - worden, als je maar ��n memory mapper wilt gebruiken - als RAMdisk. Bijvoorbeeld RAMDISK /M 2-2 voor de memory - mapper in slot 2.2 (het derde gleufje van de - slotexpander, als die in slot 2 is gestoken). - - /H : iets met ROM - Misschien dat het hiermee mogelijk is de ROMdisk van de - FS-A1GT alsnog te gebruiken onder DOS1, of zoiets. Iets - anders lijkt me niet zo logisch - maar wie het weet mag - het me laten weten! - - Verder kun je nog met R (dus zonder streepje!) opgeven dat - de RAMdisk drive A: moet zijn. Dan krijg je dus: - - RAMdisk FDD1 ( FDD2 ) - A: B: ( C: ) - - Ook kun je opgeven vanaf welk geheugenadres het RAMdisk zich - mag plaatsen. Dit doe je als volgt: - - RAMDISK S xxxx - - Waarbij xxxx het hexadecimale adres is. Bijv. E000. - - - Voorbeeld: - RAMDISK R /M/V - - Dit maakt een RAMdisk aan die alle aanwezige RAM (VRAM en - memory mapper) gebruikt, en er dan drive A: van maakt. - - - S E T B O O T . C O M - - Met dit programma kunnen bij het opstarten bepaalde dingen - veranderd worden. De bootsector wordt door dit programma - namelijk naar wens aangepast. Maar kijk wel uit hiermee, het - programma wil ook meteen je hele disk formatteren - en dat - kan best wel pijnlijk zijn, zo leert mijn ervaring hiermee. - - Achter SETBOOT kun je de volgende letters gebruiken. Het - NIET gebruiken van deze letters impliceert dus meteen dat de - omgekeerde handeling gebeurt. - - D : geen [CTRL] indrukken zorgt voor 2 - drives - K : het KANA lampje aan (alleen bij - Japanse computers) - C : het CAPS lampje aan - H : weer iets met ROM (zie ook bij RAMdisk - de optie /H) - - - Voorbeeld: - SETBOOT B:C - - Nu wordt de bootsector van de disk in drive B: zo aangepast - dat het CAPS lampje altijd aangaat, en dat je alleen 2 - drives kunt gebruiken als je [CTRL] WEL inhoudt. Het KANA - lampje gaat nu dus ook niet aan. Dit is best wel handig voor - mensen met maar ��n drive. Die virtuele drive kost normaal - namelijk meer dan 1 kB BASIC ruimte, en het is lastig om - altijd [CTRL] ingedrukt te moeten houden bij het opstarten. - - Kasper Souren diff --git a/sunrise_special/6/Turbo Modula-2.md b/sunrise_special/6/Turbo Modula-2.md deleted file mode 100644 index 5e9db59..0000000 --- a/sunrise_special/6/Turbo Modula-2.md +++ /dev/null @@ -1,130 +0,0 @@ - T U R B O M O D U L A - 2 - - - Op de disk staat MODULA2.PMA, met daarin de Turbo Modula-2 - compiler van Borland! Nu vraag je je misschien af: "Is dat - niet illegaal?" Volgens Borland zelf in ieder geval niet! - Borland ondersteunt hun CP/M software niet meer, omdat dat - betekent dat ze ook service en updates moeten geven. Daarom - doen ze net of het niet bestaat, en als je toch vraagt hoe - je eraan kunt komen, krijg je te horen dat je het maar van - iemand moet kopi�ren! - - Enfin, nadat we dit (waargebeurde) verhaal hadden gehoord - besloten we na enig overleg om de Modula-2 compiler gewoon - op de Special te zetten, om zo de drempel om met Modula-2 te - beginnen zo laag mogelijk te houden. - - - T U R B O - - Net als bij Turbo Pascal zijn er een aantal verschillen - tussen Turbo Modula-2 en standaard Modula-2. Het belang- - rijkste verschil is dat de read/write statements net als bij - Turbo Pascal maar in tegenstelling tot standaard Modula-2 - wel tot de taal behoren! - - Bij standaard Modula-2 zitten de read/write statements in - losse modules, wat betekent dat je voor elk type een aparte - read/write nodig hebt! - - In standaard Modula-2 kun je bijvoorbeeld zoiets tegenkomen: - - WriteString("Lengte: "); - WriteReal(Lengte); - WriteLn; - - In Turbo Modula-2 is het net als bij Turbo Pascal: - - WRITELN("Lengte: ", Lengte); - - Wat toch een stuk fijner is! De onhandige read/write - statements van Modula-2 is zelfs de belangrijkste reden dat - Turbo Pascal veel populairder is dan Modula-2! Maar gelukkig - hebben wij Turbo Modula-2 voor MSX en hebben wij daar geen - last van. - - Modula-2 heeft geen stringtype, je moet zelf strings maken - met ARRAY OF CHAR. Dit is bij Turbo Modula-2 nog steeds zo, - wel kunnen zulke ARRAYs OF CHAR nu worden vergeleken en - geassigned. Het onderstaande kan in Turbo Modula-2 dus wel - en in standaard Modula-2 niet: - - String := "Modula-2"; - IF String = "Turbo Pascal" THEN - WRITELN("Dit kan niet!"); - END; - - Er zijn nog meer verschillen met standaard Modula-2 (zoals - meerdimensionale open-array parameters), maar een standaard - Modula-2 source zal normaal gesproken gewoon kunnen worden - gecompileerd. Let op: de standaardmodule Storage heet bij - Turbo Modula-2 STORAGE! In hoofdletters dus, let daar op! - - - D E C O M P I L E R - - De Turbo Modula-2 compiler is een ge�ntegreerd pakket met - ingebouwde editor en 'library manager'. Als de compiler een - fout tegen komt in de source springt hij automatisch naar de - editor, als je de fout hebt verbeterd gaat het compileren - gewoon door! - - Als je een source compileert wordt er nog geen uitvoerbare - .COM file van gemaakt, je moet hem daarvoor eerst nog - linken. - - Eigen ML-routines kunnen in binaire vorm (.COM, moet wel - relocatable zijn!) of als relocatable (.REL) worden - toegevoegd! Dit is bij grotere routines veel handiger dan - bij Turbo Pascal, waarbij met pure hex-codes wordt gewerkt. - - - M E N U - - Je start Turbo Modula-2 door achter de DOS prompt "M2" in te - typen. Je komt nu in het hoofdmenu terecht. Je kunt hier een - keuze maken door de letter in te toetsen die als hoofdletter - in de menu-optie staat. De opties in het kort: - - Work file Geef de naam van de huidige werkfile op - Edit Ga naar de editor - Compile Compileer de huidige source - Run Voer een .MCD file uit - eXecute Voer een .COM file uit - Link Maak Z80-code - Options Instellingen wijzigen - Quit Verlaat de compiler - liBrarian Library manager - Dir Directory - Filecopy Kopieer file(s) - Kill Wis file(s) - reName Hernoem file(s) - Type Bekijk file - - Het interne codeformaat van de compiler is .MCD. Als je een - definition module compileert wordt het een .SYM file, een - implementation module wordt een .MCD file. Je kunt een - aantal .MCD's met bijbehorende .SYM's samenvoegen tot een - library met de librarian. - - - D E E D I T O R - - De editor is ingesteld als aanbevolen door Herman Post voor - de editor van Turbo Pascal in MCCM 61. De belangrijkste - toetsencombinaties zijn: - - CTRL-Y Wis regel - CTRL-N Voeg regel tussen - CTRL-K, CTRL-D Verlaat editor - - Voor de overige combinaties verwijs ik naar MCCM 61, blz. - 12. De editor is niet echt handig, dus het is misschien - fijner om TED te gebruiken voor het schrijven van het - grootste gedeelte van de source en de editor alleen te - gebruiken voor debuggen. De toetsencombinaties kunnen - eventueel naar eigen smaak worden ingesteld met INSTM2.COM. - - Stefan Boer - diff --git a/sunrise_special/6/Valburg systeem.md b/sunrise_special/6/Valburg systeem.md deleted file mode 100644 index c269807..0000000 --- a/sunrise_special/6/Valburg systeem.md +++ /dev/null @@ -1,146 +0,0 @@ - V A L B U R G - S Y S T E E M - - - Het begon allemaal toen ik las dat Alex v.d. Wal Gianna - Sisters professioneel noemde, ik voelde me meteen geroepen - om ook eens iets te schrijven over mijn aanpak van grote - projecten. Maar we beginnen bij het begin. - - G I A N A S I S T E R S - - Giana Sisters is eigenlijk niet erg professioneel opgezet. - Ik ben begonnen in WBASS2 met de scroll-routine. Dat was een - heel elementair iets dat ik af moest hebben voordat er met - iets anders kon worden begonnen. Daarna kwamen - achtereenvolgens erbij: de sprite routines, besturing van de - speler en botsen van de speler tegen de achtergrond, - vijanden, interactie van vijanden met de speler, en - vervolgens werden alle onderdelen uitgewerkt tot het spel - dat het nu is. - - Ik heb natuurlijk ook een editor gemaakt om de velden in te - ontwerpen, en een converter om de SCREEN 4 karakters aan te - maken. Langzamerhand bleek dat de source te groot werd om - nog in WBASS2 mee te werken. Ik moest toen tegen mijn zin in - overschakelen op GEN80. Dus eerst naar DOS, de tekst - editten, GEN80, naar BASIC, uitproberen, werkt niet, naar - DOS, etc.. Achteraf gezien vrij omslachtig. - - Op een gegeven moment heb je dan de speelroutine zo'n beetje - wel af en moet je bezig gaan met een programma eromheen dat - highscores doet, stages inlaadt, etc.. Ik heb er toen voor - gekozen om daar een los programma van te maken dat de main - in kon laden. Geen kernel dus, geen eigen BIOS, niks - daarvan. Wel werd de BIOS bijna geheel gepasseerd. Ik - gebruikte hem alleen nog voor schermwisselingen en joystick - poort uitlezen. - - Het resultaat mag er zijn. Een echte Mario-kloon waar heel - MSX'end Nederland zo op zat te wachten. Maar veel kritiek - kreeg ik wel. Het was grafisch niet mooi genoeg, ik had niet - genoeg fade-in en fade-outs erin zitten en Loek van Kooten - gaf nog kritiek op het uit Friesland afkomstig zijn van de - club. ("gemene valletjes bedacht door de makers, maar die - komen dan ook maar uit Friesland") - - - T O T A A L A N D E R E A A N P A K - - Er is nogal wat veranderd na dat tweede spel. Ik zal nu - eindelijk to the point komen en vertellen hoe ik vind dat - het echt moet, en waarom. - - Allereerst ben ik me vreselijk gaan afzetten tegen WBASS2. - Door het gemis van MACRO's, relocatable files, een goede - INCLUDE functie, door het te kleine werkgeheugen en doordat - het onder BASIC werkt. Snel gaat het wel, en voor beginnende - ML programmeurs of demomakers is het helemaal zo gek nog - niet. - - Programma's maken gaat het beste onder DOS. Liefst met - ramdisk of HD en met een tR of 7 MHz als het even kan. DOS - heeft het voordeel dat er 2 keer zoveel ruimte beschikbaar - is als onder BASIC. Natuurlijk kan je onder BASIC ook de - interpreter wegschakelen en de BIOS weghalen, maar onder DOS - is dat al gebeurd, dus waarvoor al die moeite? En als je - toch de BIOS wilt gebruiken dan doe je gewoon een - interslotcall. Over het algemeen zal je de functies die snel - moeten zijn toch al wel zelf hebben gemaakt. - - Ook draaien programma's die je onder DOS hebt gemaakt ook - meteen goed vanuit de bootsector. Gewoon het BDOS jump adres - naar 05H copieren en starten maar. Alle RAM pagina's staan - al voorgeschakeld. Of rename je de .COM file liever als - COMMAND.COM? MSXDOS.SYS erbij en dan is het meteen klaar. - - Dan het idee van een eigen kernel. Het idee is leuk en - klinkt heel professioneel en interessant, maar eigenlijk is - het alleen handig bij diskmagazines. Daar heb je nl. vaak - heel veel programma's met allemaal dezelfde routines. In - andere gevallen komen de routines maar een keer voor en is - het alleen maar onhandig om al die overtollige - niet-gebruikte routines in pagina 0 mee te sjouwen. - - Daarom beveel ik ook aan om libraries te maken met daarin - alle routines die je anders in een BIOS/kernel zou stoppen. - Het enorme voordeel hiervan is dat precies de routines die - jij in je programma aanroept uit de library worden gevist en - aan je programma worden geplakt! Zo gebruik je dus niets te - veel aan geheugen en hoef je ook geen kernel in te laden! - Voor mij is dat nu al de ideale manier en volgens mij weten - een heleboel mensen niet dat een linker dat kan. Lees het - voorgaande dan nog maar eens goed want het is echt - superhandig. Een linker is een zeer vernuftig stukje - software dat modulair programmeren tot kinderspel maakt. - - Dan komen we nu bij het probleem van het filesysteem. - Eigenlijk heb ik dat hiervoor al opgelost. Gewoon een - library functie die een file op een bepaald adres kan - inladen. Als het nu op sector moet komen te staan vervang je - de library functie door een sector lader met erbij gelinkt - de data met de plaats van de files. Aan het programma zelf - hoeft niets te worden veranderd, gewoon opnieuw linken en je - programma laadt op sectorniveau. - - - P L A A T J E S E N M U Z I E K L I N K E N - - In plaats van inladen zou je natuurlijk ook de plaatjes en - muziek in je programma kunnen stoppen. Alleen zit je dan met - het probleem waar? Je kan het natuurlijk heel precies aan - het einde van je programma zetten, maar als je programma dan - wat groter wordt moet je het adres weer aanpassen en - bovendien dat hele plaatjes er weer aan CONCATten of - misschien zelfs met de hand eraan plakken als je geen DOS 2 - hebt. - - Je raadt al wat de oplossing is... linken. maak van de - muziekfile of grafische file een .REL file. Eraan linken en - de linker plakt alles precies op de juiste plaatsen aan - elkaar en vult daarna de juiste adressen in in jouw - programma. Handiger kunnen we het niet maken. - - Misschien denk je nu wel "te mooi om waar te zijn, dat duurt - veel te lang en bovendien is het alleen maar theorie. Hij - gebruikt zelf vast WBASS2". Helemaal mis! Het linken gebeurt - razendsnel. Over het algemeen doet de linker er nooit langer - over dan 30 seconde, en dan zoekt ie dus library's uit en - plakt ie plaatjes aan je programma en alles. Het tweede is - ook niet waar want zelf heb ik (samen met Jouke Dijkstra, - die mag wel eens genoemd worden) alles al in de praktijk - gebracht. Ik heb zelf al een programma gemaakt waarin in een - file alle muziek, plaatjes etc. erbij zitten en dan staat - het ook nog een op sector en wordt ingeladen vanuit de boot. - (zonder MSXDOS.SYS) - - - J A , I K W I L O O K L I N K E N - - Dat kan, join the club. Als je interesse hebt in hoe dit - alles in de praktijk in zijn werk gaat, of je hebt - belangstelling voor de library's en programma's waarmee dit - alles moet worden bewerkstelligd dan hoef je alleen maar - even contact op te nemen met mij via post, telefoon of - echomail, uploads/downloads alleen via Piramide BBS. - - Jan van Valburg diff --git a/sunrise_special/6/Waarom Modula2.md b/sunrise_special/6/Waarom Modula2.md deleted file mode 100644 index 827a710..0000000 --- a/sunrise_special/6/Waarom Modula2.md +++ /dev/null @@ -1,109 +0,0 @@ - W A A R O M M O D U L A - 2 ? - - - Op de vorige Special had ik aangekondigd een cursus Turbo - Pascal te starten. Dat deed ik eigenlijk bij gebrek aan - beter, want ik had liever een Modula-2 cursus aangekondigd. - Ik dacht toen dat er helaas geen Modula-2 compiler was voor - MSX, zodat we het dan maar met Turbo Pascal moesten doen. - - Een paar maanden later zag ik opeens een Modula-2 compiler - in Mari's Games BBS, die ik natuurlijk meteen heb gedownd. - Dit bleek Turbo Modula-2 van Borland te zijn! - - - F A N - - Ik ben een echte Modula-2 fan! De voordelen van Modula-2 en - Pascal zijn dat het eigenlijk de enige bekende talen zijn - die speciaal bedoeld zijn voor gestructureerd programmeren. - Natuurlijk kun je ook met Modula-2 en Pascal nog knoeien, - maar de talen nodigen in principe uit tot netheid. Dit in - tegenstelling tot C, waarin de meeste programmeurs er een - onleesbare puinhoop van maken. - - En waarom kies ik dan voor Modula-2 en niet voor Pascal? - Beide talen zijn door Niklaus Wirth ontworpen en lijken dan - ook vrij veel op elkaar. Wirth heeft Modula-2 echter later - ontworpen dan Pascal, waarbij hij een groot aantal minder - sterke punten in het ontwerp van Pascal heeft verbeterd. - Borland heeft een aantal voordelen van Turbo Pascal ten - opzichte van standaard Pascal overigens van Modula-2 - afgekeken! - - - V O O R D E L E N - - De voordelen van Modula-2 ten opzichte van Turbo Pascal - zijn: - - - Modula-2 werkt met modules, waardoor op een zeer handige - wijze modulair kan worden geprogrammeerd. De modules - worden apart gecompileerd, als je iets veranderd in een - module hoeven de andere modules dus niet opnieuw te worden - gecompileerd! (Bij Turbo Pascal is dat wel zo.) Bovendien - worden alleen de procedures die je werkelijk gebruikt uit - de module ge�mporteerd, zodat de executable niet onnodig - groot wordt. - - De structuur van IF, WHILE, etc. statements is bij - Modula-2 veel logischer waardoor je veel minder snel - fouten maakt dan bij Turbo Pascal. - - Het maakt bij Modula-2 niet uit in welke volgorde je de - procedures zet, terwijl Turbo Pascal een (onlogische) - volgorde oplegt (namelijk dat procedures die vanuit een - andere procedure worden aangeroepen erboven moeten staan, - eronder is logischer omdat je topdown programmeert). - - Modula-2 is case-sensitive en alle gereserveerde woorden - moeten met hoofdletters worden geschreven. Voor sommigen - lijkt dit misschien een nadeel, maar het is bijvoorbeeld - erg handig om een variabele Char van het type CHAR te - hebben (dat kan bij Turbo Pascal niet omdat Turbo Pascal - geen verschil maakt tussen hoofd- en kleine letters) en - het maakt de programma's beter leesbaar. Ik schrijf in - Turbo Pascal ook alle gereserveerde woorden in - hoofdletters, maar helaas behoor ik daarmee tot een - minderheid. - - Genest commentaar mag in Modula-2 wel en in Turbo Pascal - niet. Dit is erg vervelend bij Turbo Pascal, als je daar - een flink stuk van je source tussen {} wilt zetten kan dat - alleen als er geen commentaar in voorkomt. - - Modula-2 heeft 'open array' parameters, waardoor je - makkelijker universele procedures kunt maken voor arrays. - - De stapgrootte van een FOR-loop is bij Modula-2 variabel - (bij Turbo Pascal zijn alleen +1 en -1 mogelijk). - - Er zijn nog wel meer verschillen/voordelen te noemen maar - deze lijst lijkt me wel voldoende reden om Modula-2 te - prefereren boven Turbo Pascal. - - - N A D E E L - - Eigenlijk het enige nadeel van Modula-2 ten opzichte van - Turbo Pascal is dat Turbo Pascal veel meer wordt gebruikt. - Dit heeft als gevolg dat er meer aandacht voor is in de vorm - van cursussen in tijdschriften, boeken en libraries. - - Maar als dit een reden zou zijn om toch Turbo Pascal te - gebruiken, dan vraag ik me af waarom er nog MSX gebruikers - zijn. Er zijn immers veel meer PC-gebruikers... - - - A L L E E N T E K S T - - Ik hoor vaak van andere MSX'ers: ik programmeer niet in - Turbo Pascal omdat je dan geen grafische instructies hebt. - Je kunt alleen maar met (trage) READ/WRITE op een - tekstscherm werken. Dit zelfde 'nadeel' geldt ook voor Turbo - Modula-2. - - Maar natuurlijk kun je een library maken met grafische - instructies, en dat is wat ik binnenkort ga doen. Dus op - Sunrise Special #7 kun je een flinke library verwachten met - een grote hoeveelheid handige routines voor de VDP, zodat je - Modula-2 dan ook voor grafische dingen kunt gebruiken. - - Kortom, ik hoop dat een groot aantal van jullie over zal - stappen op Modula-2! - - Stefan Boer diff --git a/sunrise_special/7/CMD Mode V9958.md b/sunrise_special/7/CMD Mode V9958.md deleted file mode 100644 index 8f7343a..0000000 --- a/sunrise_special/7/CMD Mode V9958.md +++ /dev/null @@ -1,148 +0,0 @@ - C M D M O D E V 9 9 5 8 - - - De videochip van de MSX2+ en de MSX turbo R (de V9958) heeft - er ten opzichte van de V9938 drie nieuwe registers bij - gekregen. Dit zijn: - - 7 6 5 4 3 2 1 0 - R#25 - CMD VDS YAE YJK WTE MSK SP2 - R#26 - - HO8 HO7 HO6 HO5 HO4 HO3 - R#27 - - - - - HO2 HO1 HO0 - - De betekenis van de bits: - - HO0-HO8: horizontaal scrollen, bij HO0-HO2 is rechts - de positieve richting en bij HO3-HO8 is - links de positieve richting - SP2: scroll horizontaal met 2 pagina's als dit - bit gezet is, met 1 pagina als het 0 is - MSK: de scroll hapt normaal aan de linkerkant, - met dit bit gezet worden 8 pixels aan de - linkerkant afgedekt - WTE: als dit bit gezet is, wordt de toegang tot - alle VDP poorten in de WAIT stand gezet - als de CPU met het VRAM bezig is. Dit - gebeurt niet in andere gevallen waarbij dit - wel handig zou zijn zoals terwijl de VDP - met een commando bezig is, terwijl de eerste - byte van een registeraccess al ontvangen is - of als de eerste byte van een paletaccess - al ontvangen is - YJK: YJK mode aan/uit (SCREEN 12) - YAE: YAE mode aan/uit (SCREEN 10/11) - VDS: met dit bit kun je het CPUCLK signaal - vervangen door het VDS signaal, wat het nut - daarvan is, is onbekend - CMD: als dit bit gezet is kunnen commando's ook - in SCREEN 0-4 worden gebruikt, waarbij de - parameters zo moeten worden ingesteld alsof - SCREEN 8 actief is - - - C M D M O D E - - Over het laatstgenoemde bit (bit 6 van R#25) gaat dit - artikel. Iedereen die het V9958 Technical Data Book of een - tekst over de V9958 registers heeft gelezen weet dat dit bit - bestaat, maar ik heb nog nooit gehoord dat iemand het - gebruikt! En toch kun je er hele leuke dingen mee doen! - - Bij de V9938 en als het CMD bit 0 is bij de V9958 kun je - alleen commando's gebruiken in SCREEN 5 en hoger. Als je het - CMD bit echter hoog maakt, kun je ook commando's gebruiken - in SCREEN 0-4! - - Nu moet je niet denken dat je lijnen kunt trekken in SCREEN - 0 of dat je kunt kopi�ren zoals je zou verwachten in SCREEN - 2, want dat is natuurlijk onzin. Je kunt niet zoiets als - COPY(10,15)-(20,35)TO(100,90) doen in SCREEN 2, omdat het - geen bitmap mode is. - - De truuk is dat de VDP bij het uitvoeren van de commando's - net doet alsof SCREEN 8 actief is! Je moet dus alles - omrekenen naar de VRAM indeling van SCREEN 8. - - Een paar voorbeeldjes zullen dit duidelijk maken. We gaan er - steeds van uit dat het CMD bit is gezet. Stel je wilt een - "A" zetten op positie (0,0) in SCREEN 0:WIDTH 80. Dan kan - dat met VPOKE 0,65 of met LOCATE 0,0:PRINT "A". Maar het kan - ook met PSET(0,0),65! Helaas niet in BASIC want die geeft - nog steeds een Illegal function call, maar wel als je het - rechtstreeks met de commando registers doet! - - Nu willen we een B zetten op positie 8,17. Dat kan dus NIET - met PSET (8,17),66!!! Je moet namelijk denken aan de VRAM - indeling van SCREEN 8. Het adres van 8,17 is 8 + 17*80 = - 1368. Nu moet je dit omrekenen naar het pixel in SCREEN 8 - dat op dat adres staat. X = 1368 MOD 256 = 88, Y = 1368 \ - 256 = 5. Dus met PSET(88,5),66 zet je een B op positie 8,17. - - - W A T H E B J E E R A A N ? - - Wat heb je hier aan zul je denken? Wel, aan PSET heb je niet - veel en aan LINE ook niet. Maar met HMMM (COPY) en HMMV - (LINE,BF) kun je bepaalde dingen een stuk sneller en - handiger doen! - - Bijvoorbeeld het scherm bewaren om het later weer te - herstellen. Met een HMMM kun je het scherm naar een ander - stuk VRAM kopi�ren. Het neemt 24*80 = 1920 bytes in beslag, - dat komt overeen met 7.5 lijnen in SCREEN 8, dat moeten we - naar boven afronden naar 8. Dus doen we COPY(0,0)-(255,7) TO - (0,128). Nogmaals, dit kan niet met het BASIC commando COPY - worden gedaan, ik gebruik alleen deze notatie voor de - duidelijkheid. Je moet dit zelf omzetten naar de juiste data - om naar register R#32 t/m R#46 te sturen: - - DB 0,0,0,0 ; source - DB 0,0,128,0 ; destination - DB 0,1,8,0 ; size - DB 0,0,#D0 ; HMMM - - Er wordt zo nog iets meer gekopieerd (2048 bytes om precies - te zijn), maar dat maakt niet uit. Met precies de - omgedraaide copy kun je het scherm nu weer zeer snel - herstellen. Deze methode kost geen RAM om het scherm op te - slaan (wel VRAM natuurlijk maar in SCREEN 0-4 gebruik je - toch alleen maar de eerste 16 kB) en wat belangrijker is: - het kost weinig processortijd! Je hoeft alleen maar die 15 - bytes naar de commandoregisters te sturen en de VDP doet de - rest van het werk. Als je het 'normaal' programmeert kan dat - nooit zo snel! - - Met HMMV kun je het scherm snel vullen met een bepaald byte. - Je kunt het scherm bijvoorbeeld in een oogwenk met A's - vullen, veel sneller dan je dat ooit op een andere manier - (gewoon met VPOKEn) zou kunnen doen. De commandodata ziet er - dan zo uit: - - DB 0,0,0,0 ; dummy - DB 0,0,0,0 ; destination - DB 0,1,8,0 ; size - DB #41,0,#C0 ; HMMV met #41 (='A') - - Hetzelfde resultaat kan ook bereikt worden door de VDP klaar - te zetten voor VRAM schrijven vervolgens 1920 maal OUT - (#98),#41 doen, maar dat kost veel meer moeite voor de CPU - en duurt bovendien langer. - - Enfin, je kunt zelf wel bedenken wat er nog meer mogelijk is - met de CMD mode, bijvoorbeeld in SCREEN 4. Je kunt misschien - ook leuke dingen doen met logische operaties, denk erom dat - je dan wel LMMM etc. moet gebruiken. Ik heb al zitten denken - voor toepassingen bij de blinkmode van SCREEN0:WIDTH 80, - maar ik geloof niet dat dat handiger gaat dan de routines - die al eerder op de Special hebben gestaan. - - - N A D E E L - - Een nadeel van de CMD mode is dat hij alleen op de V9958 - zit, en programma's die in SCREEN 0-4 worden gemaakt meestal - ook voor MSX2 zijn. Maar er zijn natuurlijk uitzonderingen - zoals een MODplayer, en daarbij zou je dit zeer goed kunnen - gebruiken. - - Stefan Boer diff --git a/sunrise_special/7/Diskette elende.md b/sunrise_special/7/Diskette elende.md deleted file mode 100644 index f189039..0000000 --- a/sunrise_special/7/Diskette elende.md +++ /dev/null @@ -1,299 +0,0 @@ - D I S K E T T E E L L E N D E - - - Iedere MSX'er heeft dit waarschijnlijk al eens meegemaakt; - een disk die na het saven van een file 'kapot' is doordat - tijdens de save aktie van diskette gewisseld is. Dit - probleem is al heel lang bekend (de oplossingen ook - overigens) en ik vertel dan ook weinig nieuws, maar ik heb - nog nooit ergens na kunnen lezen wat er allemaal precies - fout gaat. - - Ik wil me hier vooral op MSXDOS-1 richten omdat dit voor - diskettes de grote boosdoener is. Diskettes kunnen in - tegenstelling tot hun grotere broers, de harddisks uit hun - gleuf geknikkerd worden. Dat is op zich heel handig, maar - het probleem is dat de BDOS hier praktisch niet achter kan - komen. De BDOS is namelijk blind voor onaangekondigde - diskwisselingen. Snapt u nu waarom een Apple Macintosh geen - eject knop heeft? Het enige wat de BDOS kan zien is dat er - tijdens een diskaktie geen disk in de drive zit, waarna deze - kan vragen om het ding weer terug te plaatsen. Het woordje - 'deze' in de vorige zin is in dit verhaal van cruciaal - belang. De BDOS gaat er nl. vanuit dat tijdens kritieke - akties altijd de fysiek gelijke diskette in de drive zit. - - Theoretisch is het mogelijk dat de BDOS ook daadwerkelijk - controleert of dit het geval is, maar dat zou een diskaktie - zo traag maken dat iedereen nog vrolijk met cassettetapes - zou werken omdat die sneller zouden zijn. De BDOS eist dus - een bepaalde discipline van de gebruiker om tijdens kritieke - diskakties NOOIT van diskette te wisselen. Ik ben echter van - nature een onderzoeker (lees: eigenwijs) en heb eens gekeken - naar wat er nu precies mis kan gaan. - - - H E T L E Z E N V A N E E N F I L E - - Het inlezen van een file begint met het openen ervan. Bij - DOS1 worden nu de 3 FAT sektoren en de directorysektor waar - de te laden file in genoemd is in het geheugen geladen en - die blijven daar ook. Vervolgens kan de file gelezen worden - waarbij in het geheugen 1 sektor met laadgegevens wordt - bijgehouden. Dit wordt gedaan om bv. 4 bytes uit de file te - kunnen lezen. Eerst wordt de sektor ingeladen en vervolgens - worden de 4 bytes naar het DMA gekopieerd. - - Tijdens het inladen kan de gebruiker tot de ontdekking komen - dat dit een oude versie van de file is waarna hij de disk in - een reflex uit de drive neemt. Indien hij deze na protesten - van de BDOS terug stopt, dan is er niets aan de hand. Stopt - hij echter een andere disk terug in de drive met de nieuwere - versie van de file, dan gaat het fout. Alle informatie over - waar de file precies op de disk te vinden is staat nl. al in - het geheugen (FAT + dir.sektor) en op deze nieuwe disk kan - deze file wel op een heel andere positie staan. In dit geval - gaat het lezen dus wel door, maar wordt alleen rotzooi - gelezen. - - Geconcludeerd mag worden dat het wisselen van diskettes - tijdens een laadaktie resulteert in een fout ingelezen file, - maar dat de diskettes zelf heel blijven. Hoe anders is dit - bij een schrijfaktie. - - - H E T S C H R I J V E N V A N E E N F I L E - - Tijdens het cre�ren van een file zoekt de BDOS de directory - sektoren af naar een lege positie voor de nieuwe file. Zodra - een plaats gevonden is wordt o.a. de filenaam alvast - ingevuld. De sektor waar de directory entry in terecht komt - blijft in het geheugen staan. Nu wordt in de FAT naar een - geschikte startpositie voor de file gezocht. De FAT wordt - overigens ook in het geheugen gelezen. - - Laten we zeggen dat de file 1kB lang is en dat de eerste 128 - bytes nu weggeschreven worden waarbij niets fout gaat. Nu - haalt een onverlaat echter de disk uit de drive waarna de - volgende 128 bytes geschreven worden. Wat zal er volgens jou - gebeuren tijdens deze tweede schrijfaktie? Een disk-offline - melding misschien? - - FOUT!! De schrijfaktie gaat wonder boven wonder goed. Dat - komt omdat ook tijdens een schrijfaktie ��n sektor met - informatie in het geheugen wordt bijgehouden en omdat een - sektor 512 bytes groot is, wordt deze buffer nog niet naar - disk geflushed. - - Nu wordt het resterende deel van de 1kB file in 1 keer - weggeschreven en komt de diskdrive dus wel degelijk in - aktie. Hier doen zich drie potenti�le foutsituaties voor, te - weten: - - Disk offline - - Disk full - - Physical I/O error (kras op de magnetische laag etc.) - - In een eerder artikel op Sunrise Magazine Special #4 heb ik - al eens geprobeerd uit te leggen hoe de error handling van - de BDOS werkt (met die dubbele pointer constructie etc.) Bij - een disk offline wordt nu naar een eventueel ge�nstalleerde - error handler gesprongen. Zo ook bij een fysieke I/O error. - Bij een disk full wordt echter alleen register A = 1 - (MSXDOS-1 call) gemaakt en wordt naar de aanroepende routine - terug gesprongen. - - De vraag op dit punt is, wat moet je nu doen? Indien er een - disk offline is geweest die nu is opgelost, maar de persoon - een andere disk in de drive heeft gestopt, dan is de kans - 99.99% dat deze nieuwe disk bij de minste of geringste - volgende diskaktie onherstelbaar beschadigd raakt doordat - zowel de FAT als de directory sektor van de andere disk op - de huidige geschreven worden. - - Even terug naar de vraag: "wat nu te doen ?". Indien de file - wordt gesloten, dan wordt de in het geheugen opgeslagen - directorysektor teruggeschreven naar de disk. Dit wordt ook - met de FAT sektoren gedaan. De nieuwe disk wordt dus met - voor hem onzinnige informatie gevuld, maar indien de - originele disk is teruggestopt dan gaat het (uiteraard) - goed. - - Indien de hele schrijfaktie domweg afgebroken wordt, dan zal - de nieuwe disk niet vernield worden, of wel ?? Het antwoord - daarop is dat deze disk in eerste instantie inderdaad heel - blijft. Tijdens mijn testjes heb ik in die situatie eens de - directory opgevraagd en zag tot mijn stomme verbazing de - directory van de schijf die ik net gewisseld had op mijn - beeldscherm verschijnen. (Opm: De totale directory van die - schijf pastte in 1 sektor) De BDOS had kennelijk niet door - dat er een andere disk in de drive was gestoken. Of dit - onder DOS-2 ook het geval is weet ik overigens niet, maar ik - kan me voorstellen dat het hier wel goed gaat omdat hier met - Volume-IDs gewerkt wordt. - - Waarom kijkt de BDOS in deze situatie niet naar de disk om - te kijken of deze misschien gewisseld is? Anders doet hij - het immers altijd (het zou niet best zijn als dat niet - gebeurde). Het enige wat de oorzaak van dit probleem kan - zijn is het feit dat de file waarop de schijfaktie fout ging - nooit gesloten is. De BDOS neemt immers aan dat een diskette - alleen tussen het lezen en schrijven van komplete files - gewisseld wordt. Het domweg afbreken van de schrijfaktie - omdat er iets fout ging is dus NOOIT goed. - - Iets anders is BDOS call 13; de drive reset. Indien deze - call wordt uitgevoerd voordat een gecre�erd bestand gesloten - is, dan gaat het toch fout doordat o.a. de FAT sektoren weer - worden teruggeschreven. In deze situatie dus niet gebruiken. - - - D E M O R A A L - - De moraal van dit verhaal is dat indien je een file cre�ert, - je deze ook moet sluiten. Doe je het niet, dan verschuif je - de ramp alleen maar in tijd naar voren, maar hij zal komen ! - Dat hierdoor diskjes vernield kunnen raken doodat ze - tussentijds gewisseld worden is jammer, maar doe je het niet - dan biedt alleen het uitzetten van de computer een garantie - dat de disk bij de volgende diskaktie in orde blijft. Het - zal hem wel aan mij liggen, maar de melding "Please reset - your MSX before continuing" lijkt me alleen in Metal Gear - grappig, maar niet in een tekstverwerker. - - Wat dient er nu te gebeuren indien een disk schrijfaktie - afgebroken wordt door de gebruiker (disk offline met - (A)bort) of de BDOS (disk vol)? Welnu, als eerste moet de - file gesloten worden. Daarna moet de gemaakte rotzooi nog - opgeruimd worden, door de aangemaakte file te deleten. Als - dat gebeurt is, is er niets aan de hand en kan de komplete - aktie later nog eens herhaald worden op een disk die meer - kans van slagen biedt. - - - P R O G R A M M E U R S E N D I S K E T T E S - - Gebruikers moeten weten dat ze tussen het cre�ren van een - file en het sluiten ervan met hun tengels van de diskdrive - af moeten blijven. Programmeurs moeten er met wat praktische - programmeer psychologie voor zorgen dat mensen niet in de - verleiding komen om het toch te doen. Tevens moeten ze - aangeven wanneer het laad/save proces begint en eindigd. - - Neem als voorbeeld MoonBlaster. Het filemenu van dit - meesterwerk laat weinig te wensen over. Het is voor zowel - eencellige wezens, Stefan Boer en mensen overduidelijk - wanneer de computer bezig is met laden of saven. Het lampje - van de diskdrive knippert nl. uiterst vrolijk tijdens zo'n - aktie waarbij (samples buiten beschouwing gelaten) geen - verwarrende pauzes voorkomen. Dat laatste voorkomt - vroegtijdige eject neigingen. - - Een puntje van kritiek is wel dat MoonBlaster 'mislukte' - files niet delete bij bv. een disk full error. - - Abort en Retry opties tijdens een schrijfaktie mogen dus ook - wel. Het schrijfproces mag immers zonder het sluiten van de - file toch niet afgebroken worden en dus mag je de gebruiker - best de kans geven om de fout te herstellen. Dergelijke - opties zijn echter geen must. Een retry omdat iemand de disk - uit de drive haalt en deze daarna weer terug stopt zou - eigenlijk met een hatelijke "Blijf daar van af met je fikke" - sample beantwoord moeten worden en niet met het redelijk - beschaafde "Eh sorry, zal ik het nog eens proberen?". - - - T E C H N I S C H E D E T A I L S - - Even resumerend: - - Bij het laden van een file mag je van de gebruiker - verwachten dat hij van de eject knop af blijft. Doet hij - het toch, dan kan het geheugen corrupt raken, maar de disk - blijft tenminste heel. - - Bij het saven waarbij fouten optreden moet je niet gewoon - doen alsof je neus bloed, maar moet je netjes de rotzooi - opruimen. Zorg er m.b.v. je programma voor dat de - gebruiker niet in de verleiding komt om van diskette te - wisselen, zodat dit zo goed als altijd goed zal gaan. - - Het valt op dat het eigenlijk ontzetend vaak goed gaat. - Blijkbaar komt men niet zo snel op het idee om tijdens een - schijfaktie van disk te wisselen. Dit is dus blijkbaar niet - zo'n probleem. Er is echter een situatie denkbaar waarbij in - verhouding veel meer diskettes vernield raken. Stefan Boer - heeft deze situatie op Sunrise Special #1 ook al beschreven. - De situatie treedt op wanneer het cre�ren van een file - mislukt door een 'write protected' diskette. De gebruiker - stopt nu een nieuwe disk in de drive en drukt op (r)etry. - Deze nieuwe disk wordt nu vernield indien de error handler - verkeerd geschreven is. Hier is een (r)etry dus niet - ongevaarlijk! - - - ! ! ! B E L A N G R I J K ! ! ! - - - Een vroeger (ook door mij) sterk gepropageerde methode om - een retry uit te voeren in de BDOS error handler was door - register C=1 te maken, gevolgd door een RET instruktie. Dit - systeem werkt vaak goed, maar in de hierboven beschreven - situatie gaat het hopeloos fout. Het geval wil nl. dat de - FAT en directory sektor van de originele disk al in het - geheugen staan op het moment dat een "write protected" error - optreed. Na een (R)etry wordt echter niet meer gekeken of de - diskette gewisseld is. Tijdens het schrijven van de file - worden dus met hoge waarschijnlijkheid andere files - overschreven en na het sluiten van de file staat er - plotseling een verkeerde FAT en directory sektor op de - nieuwe disk. - - Samengevat: DOE NIET LD C,1 gevolgd door RET om een retry - optie te implementeren, maar doe het zoals de abort optie - werkt!!!! Herstel de stack en belangrijke registers zoals - ze voor de aanroep naar de BDOS waren en JP terug naar de - BDOS. Nu worden nl. eerst weer de FAT en directory van de - potentieel onbekende disk ingelezen. Ik heb dit geprobeerd - en het klopt als een bus. - - - C O N C L U S I E S - - Deze hele discussie over wat er nu precies moet gebeuren om - disk crashes te voorkomen loopt al een tijdje. Binnen - Sunrise leeft bij monde van Stefan Boer al geruime tijd de - overtuiging om diskakties bij foutsituaties zo snel mogelijk - af te breken (waarbij ik niet weet of hij adviseert ze eerst - te sluiten, maar dat zal wel), maar dat lijkt me dus alleen - maar gevaarlijker dan een keurige afhandeling. - - Kortom, neem aan dat de gebruiker niet gek is en handel een - schrijffout beschaafd af (sluiten en deleten). Zorg echter - wel voor een beetje transparantie van akties zodat - gebruikers niet in het ongewisse zijn over het feit wanneer - de diskaktie echt klaar is (lees: wanneer de file gesloten - is). Een tekstje "saving file..." op een statusbalk is bv. - een hele goeie. Verder MOET je er dus voor zorgen dat de - retry optie in de error handler goed ge�mplementeerd is. - - Op Sunrise Special #4 staat ook een listing van mijn hand - over diskerror afvanging onder DOS1 (en dus ook DOS2 - alhoewel deze eigen en betere routines heeft). Deze listing - werkt wel aardig en is leuk voor demo's en zo, maar het is - wat beperkt en de LD C,1 ; RET bug in de error handler zit - er ook in. Ik heb (met behulp van dit onderzoekje) de - routines nog eens dunnetjes over gedaan, waarbij vooral de - veiligheid van disk I/O prioriteit heeft gekregen. Affijn, - ik ben van mening dat deze nieuwe routines heel veel beter - en veiliger zijn dan de vorige en raad het gebruik van de - oude af. Lees echter ook de tekst op de volgende submenu - optie die wat uitgebreidere uitleg over de listing en - routines geeft. - - Ik vind het redelijk om van gebruikers het besef te vragen - dat ze zolang het disklampje brandt niet aan de ejectknop - moeten komen. Je kunt immers ook aan mensen vragen om bij - een rood verkeerslicht te wachten. Diegenen die dat niet - doen lopen dan het risiko om 5 liter rood lichaamsvocht aan - het ZOAB asfalt kwijt te raken, maar dat wisten ze - vantevoren. - - Alex van der Wal diff --git a/sunrise_special/7/Erix Driver.md b/sunrise_special/7/Erix Driver.md deleted file mode 100644 index 586d9b8..0000000 --- a/sunrise_special/7/Erix Driver.md +++ /dev/null @@ -1,399 +0,0 @@ - E R I X D R I V E R 1 / 2 - - - - W A A R O M E E N D R I V E R ? - - Het nut van een driver is het schrijven van toepassingen - voor RS232C, zonder dat je voor elke interface een apart - programma moet maken. Zo is het handig om een modem - programma wat je in combinatie met een SONY RS232C hebt - geschreven, deze door anderen gebruikt kan worden terwijl - die bv. een Philips NMS1210 hebben. - - - D E E I S E N A A N E E N D R I V E R - - Een driver moet aan verschillende eisen voldoen, wat die - eisen zijn ligt aan de toepassingen ervoor. - Ik ben toen een lijstje op gaan stellen van eisen die ik aan - een driver zou gaan stellen, de belangrijkste eisen staan - hieronder : - - - Driver moet functioneren onder MSX-DOS1 en MSX-DOS2, en - het liefst ook BASIC - - Driver voor verschillende typen interfaces moeten door - programma's gebruikt kunnen worden zonder speciale - aanpasssingen - - De driver moet snel zijn - - De driver moet resident blijven na installatie, zodat - het mogenlijk is van programma naar programma te - springen, zonder dat het nodig is om opnieuw de driver - in te laden. - - Er zijn al wel drivers die een aantal van deze eisen - bevatten, maar geen van allen doet dat ook werkelijk. - - Huib Walta had al een driver gemaakt die onder MemMan werkt, - maar die miste een van de eisen helemaal, en dat was - snelheid. MemMan is helaas niet snel genoeg om hoge - baudrates aan te kunnen. Dit komt doordat een MemMan TSR pas - aangeroepen wordt als een reeks interslot calls gebruikt - zijn. Aan de rest van de eisen wordt wel voldaan. - - De BASIC driver van Pier Feddema is ook goed, maar is helaas - alleen geschikt bij gebruik onder DISK-BASIC. De driver is - wel sneller dan de MemMan TSR die Huib Walta gemaakt heeft, - maar aangezien ik onder DOS wil werken voldoet ie voor mij - niet. - - Huib Walta heeft ook nog een driver gemaakt die onder - Turbo-Pascal werkt, maar deze driver is niet resident, en - zal elke keer vanuit DOS gelinked moeten worden aan je - programma. - - Toen ik geen drivers kon vinden die aan mijn eisen voldeden, - en ik toevallig genoeg informatie tegenkwam om de SONY - RS232C te kunnen aansturen, besloot ik om zelf dan maar een - driver te schrijven. - - - D E P R O B L E M E N V A N - E E N D R I V E R - - Toen ik begonnen was met het schrijven van een driver, kwam - ik meerdere problemen tegen..... - - Er moet een manier zijn om alle functies van de driver aan - te kunnen spreken, die voor alle drivers voor verschillende - interfaces hetzelfde is. Dit is simpel op te lossen door er - een JUMP-TABLE in te zetten, die door applicaties gebruikt - kan worden. - Als dit dan gerealiseerd is, moet de applicatie natuurlijk - ook weten of de driver er is, en zo ja, waar dan die - jump-table staat. - Om dit laatste te doen, heb ik iets gedaan wat eigenlijk - niet mag in de MSX standaard, ik heb een stukje in het - werkgeheugen gebruikt om daar 4 bytes te plaatsen. De eerste - twee bytes geven aan dat de driver er is, en de twee andere - bytes wijzen het adres aan waar de jump-table in het - geheugen staat. De driver kan alleen van disk worden - geladen, dit omdat de driver een aparte loader nodig heeft - die een file van DISK wil laden. Daarom heb ik gekozen om - deze informatie op te slaan in het cassette-parameter table, - op adres &HF3FC. Cassette wordt toch meestal niet gebruikt - als er een diskdrive aanhangt, en de RS232C gebruikt gaat - worden. - Om effectief met het geheugen om te gaan is het noodzakelijk - dat de driver zo hoog mogenlijk in het geheugen komt te - staan, het liefst hoger dan dat MSXDOS.SYS zich nestelt, - zodat er naar BASIC, en weer naar DOS gegaan kan worden, - zonder dat de driver aangetast wordt. - Doordat de top van het geheugen niet vast gedefinieerd is, - is het noodzakelijk dat de driver op elk adres kan werken. - Aangezien het praktisch onmogenlijk is om de driver in - mekaar te zetten, met alleen relatieve adressen, is het - noodzakelijk dat de driver zichzelf eenmalig aan kan passen - aan een bepaald adres in het geheugen. Hiervoor is de driver - gemaakt alsof ie van adres 0 werkt. En bij de driver is een - tabel geplaatst met informatie over wat er in de driver - veranderd moet worden. Dit aanpassen wordt door een - speciale loader gedaan. - Nog een groot probleem van een driver is dat ie resident - moet zijn. Een driver inladen en die informatie op &HF3FC - te plaatsen is niet moeilijk, nu moet alleen gezorgt worden - dat de driver intact blijft als MSX-DOS in werking komt. Dit - blijkt niet erg moeilijk te zijn, het is simpel om HiMem aan - te passen, en je driver daar net boven te plaatsen. Het - nadeel is echter dat MSX-DOS dit niet slikt, en je deze - methode vanuit BASIC moet gebruiken. Een methode is om de - driver te laden vanuit BASIC, maar aangezien ik met MSX-DOS - werk heb ik gekozen om een loader de driver in te laten - laden, de driver op het juiste adres neer plaatsen, naar - BASIC toe te gaan, wat informatie in het werkgebied - aanpassen, en dan verdergaan. - Om het mogenlijk te maken dat er automatisch nog wat gedaan - wordt nadat de driver ingeladen is, is het mogenlijk om de - driver als het ware zelf de commando's te laten intikken. - Dit is heel simpel te maken door een string naar de - toetsenbord buffer te kopieren, wat pointers aanpassen, en - BASIC de controle over laten nemen. - - Nu bleef ik nog zitten met de snelheid van de driver. - Zoals bij meesten wel bekend, genereert een RS232C interface - een interrupt als er data binnenkomt. Door snel op deze - interrupt te reageren heb je het IC wat de data verwerkt - uitgelezen voordat er nieuwe data binnenkomt die deze - informatie overschrijft. - Zodra er een interrupt optreed, zorgt de Z80 ervoor dat er - automatisch een CALL uitgevoerd wordt naar adres &H0038, op - die adres staat een jump naar een ander adres waar een - routine staat wat netjes zorgt dat &HFD9A aangeroepen wordt, - even kijkt of de interrupt van de VDP is (50/60 Hz) en zo - ja, dan even &HFD9F aanroept. In deze routine wordt ook o.a. - het toetsenbord afgescanned, wat tellers bijgehouden, en nog - meer onzin. Dit alles zorgt ervoor dat deze routine - behoorlijk lastig is als er op hoge snelheid data - binnenkomt, waardoor er data verloren gaat. - Wat dit ook inhoud, is dat er minder processor tijd - overblijft om de data die ontvangen is te verwerken. Dit - houd in dat het onder BASIC bij 19200 baud zo'n beetje - ophoud als je een normale Z80 op 3.58 Mhz gebruikt. - Onder MSX-DOS is dit nog erger, als er een interrupt optreed - wordt er naar &H0038 gesprongen, vanuit hier wordt er weer - ergens anders hoog in het geheugen gesprongen, vanwaaruit - een interslot call gedaan wordt naar de BIOS ROM op adres - &H0038. Dit alles verziekt de boel zo, dat het ontvangen van - data op hoge snelheid haast onmogenlijk wordt gemaakt. - Dit is onder MSX-DOS aanzienlijk te versnellen door in het - RAM deze jump aan te passen, zodat er als er een interrupt - optreed, de driver het eerst aan bod komt. Ook het ik de - driver zo gemaakt, dat als de interrupt voor de driver - bestemd was, deze dan niet meer door het BIOS gebruikt - bekeken wordt, of eventueel het BIOS niet meer aan te laten - roepen, om zo de maximale snelheid eruit te halen. De - methode van interrupt gebruik is in te stellen, dit om zelf - te kunnen kiezen voor keyboard gebruiken of niet, want dat - is wel de consequentie hiervan. - - (vervolg, zie text 2) - - - - E R I X D R I V E R 2 / 2 - - - - S P E C I F I C A T I E S - - Controleren op aanwezigheid driver : - - Kijk of er op adres &HF3FC/&HF3FD "RS" staat, zo ja, dan - is de driver aanwezig, ander niet. - - Pointer naar jump tabel : - - Als de driver geinstalleerd is, staat er op &HF3FE een - pointer naar de jump tabel, deze tabel is momenteel 63 - bytes lang. (21 jump entry's) - Deze pointer heeft LSB op &HF3FE en het MSB op &HF3FF - - Functies : - - Offset Functie Uitleg - +0 GetVersion Geeft het versie nummer van de driver - in HL terug. [H] = main version, - [L] = sub versie, beide packed BCD - +3 Init Initialiseert de functies van de UART, - zorgt dat data ontvangen/verzonden kan - worden. - +6 DeInit Zet de driver op non-actief - Dit moet gedaan worden als de driver - niet meer gebruikt wordt, dit ivm. een - vervelende eigenschap van de Philips - NMS121x serie, die de UART niet reset - als je de computer reset. Als deze - functie dan niet gebruikt is, is het - mogenlijk dat de computer gaat hangen - als er data binnenkomt. - +9 SetBaud Stelt de baud-rate in - [H] = Transfer, [L] = Receive rate - Nadat de snelheid ingesteld is, komt - de daadwerkelijk ingestelde baudrate - weer terug in [H] en [L], dit om te - kontroleren of die gekozen snelheid - wel ingesteld kan worden. - De baud rate wordt aangegeven door een - index, hieronder een lijstje... - - Index Baudrate - 0 75 - 1 300 - 2 600 - 3 1200 - 4 2400 - 5 4800 - 6 9600 - 7 19200 - 8 38400 - 9 57600 - 10 76800 - 11 115200 - Index 8 en hoger zijn niet bruikbaar - op een SONY interface - - +12 Protocol Stelt het protocol in waarmee de - RS232C werkt - [H] Bit 0,1 is het aantal databits - 00 = 5 bits - 01 = 6 bits - 10 = 7 bits - 11 = 8 bits - Bit 2,3 is het aantal stopbits - 01 = 1 stopbit - 10 = 1.5 stopbit - 11 = 2 stopbits - Bit 4,5 stelt de parity in - 00 = none - 01 = even - 11 = oneven - Bit 6,7 van [H] moeten op nul staan, - en register [L] moet ook op nul staan, - dit voor toekomstige uitbreidingen. - +15 Channel Stel kanaal [H] in - Als je een multi-channel interface - hebt (zoals de NMS1211), kun je - hiermee instellen welk kanaal je - gebruikt. - De kanalen niet gebruikt worden met - DeInit behandeld, en bij het kanaal - wat je insteld wordt een Init - uitgevoerd. - +18 RS_In Geef ontvangen data terug in [A] - De data wordt uit een ontvangstbuffer - gelezen die momenteel 512 bytes groot - is. - Als er geen data beschikbaar is staat - is [A]=0, om te weten of er data is, - kun je RS_In_Stat gebruiken. - +21 RS_Out Stuur [A] naar de RS232C - Deze routine keert pas terug als de - data verzonden is, deze zal dus - blijven wachten als de tegenpartij RTS - laag heeft gemaakt! - Om te weten of je wel mag zenden kun - je RS_Out_Stat gebruiken. - +24 RS_In_Stat Geeft in [A] terug of er data - beschikbaar is of niet. - [A] = 0 Geen data in buffer - [A] <> 0 Data aanwezig in buffer - +27 RS_Out_Stat Geeft in [A] terug of er data - verzonden mag worden. - [A] = 0 Data mag niet verzonden - worden - [A] <> 0 Data mag verzonden worden - - +30 DTR Stelt DTR in (Data terminal ready) - [H] = 0 maak DTR laag - [H] = 255 maak DTR hoog - +33 RTS Stelt RTS in (Request to send) - [H] = 0 maak RTS laag - [H] = 255 maak RTS hoog - +36 Carrier Geeft de huidige carrier status terug - in [A] - [A] = 0 Geen carrier - [A] <> 0 Carrier aanwezig - +39 Chars_In_Buf Geeft in HL het aantal bytes dat in - de ontvangstbuffer zit - +42 Size_Of_Buf Geeft in HL de grootte van de - ontvangst buffer - +45 FlushBuf Maakt de ontvangstbuffer leeg - +48 FastInt Zorgt ervoor dat de hook op &H0038 - afgebogen wordt, of hersteld wordt. - Deze routine controleerd zelf of de - hook al of niet afgebogen is, om - dubbel installeren/herstellen te - voorkomen. - [H] = 0 Zorgt voor normale interrupt - verwerking - [H] = 1 Zorgt dat de interrupts veel - sneller afgehandeld worden. - Door eerst met [H]=0 FastInt aan te - roepen, een andere int. handler op - &H0038 te installeren, en uiteindelijk - weer met [H]=1 FastInt aan te roepen, - is het mogenlijk om nog een andere - interrupt handler actief te hebben - tegelijkertijd met de RS232C driver. - Deze methode kan, indien goed gedaan, - enorm veel snelheidswinst opleveren. - Je kunt zo bv. een keyboard handler - installeren, en het BIOS helemaal - buiten spel zetten! - +51 Hook38Stat Stel in of normale BIOS interrupts (of - de oude interrupt handler die op - &H0038 stond) nog ondersteund dienen - te worden. (Om nog meer winst te - krijgen wat betreft processortijd) - Worden "normale" interrupt afgezet, - dan wordt er nog wel gezorgd dat - systeemvariabele JIFFY blijft lopen! - [H] = 0 "normale" interrupts - [H] <> 0 Alleen RS232C interrupts - Deze functie werkt alleen als FastInt - aangeroepen is met [H]=1 - +54 ChPut_Hook Stelt in of schermuitvoer via ChPut - ook naar de RS232C verzonden dient te - worden. - [H] = 0 Geen uitvoer naar RS232C - [H] = 1 Alle uitvoer naar RS232C - [H] = 2 Zie 1, maar nu zonder deze - text op het scherm te zien. - Levert snelheidswinst op. - +57 Keyb_Hook Stelt in of binnenkomende data naar de - ontvangstbuffer moet, of in de - keyboard buffer moet worden gezet. - [H] = 0 Data naar ontvangstbuffer - [H] = 1 Data naar keyboard - +60 Get_Info Geeft in HL een pointer naar een tabel - met informatie over de driver. - - DRIVER INFO BLOCK - - Offset Bytes Description - +0 2 Versie nummer +1 bevat het hoofd nummer - +0 bevat een sub-versie, allebij Packed BCD - +2 1 Huidige ontvangs snelheid (index) - +3 1 Huidige zend snelheid (index) - +4 1 Huidig protocol - bit 0-1 Data Bits - 00 5 bits - 01 6 bits - 10 7 bits - 11 8 bits - 2-3 Stop Bits - 01 1 stopbit - 10 1.5 stopbits - 11 2 stopbits - 4-5 Parity - 00 geen - 01 even - 11 oneven - 6-7 0 niet gedefinieerd - +5 1 ChPut_Hook status - +6 1 Keyboard_Hook status - +7 1 Huidige RTS status - +8 1 Huidige DTR status - +9 1 Huidig kanaal - +10 1 Hardware info - 0 = Geen informatie - 1 = ASCII monochannel compatible - 2 = NMS121x interface (multichannel) - 3!= MT-Telcom, aangepast voor RS232C - 4!= NMS1250, aangepast voor RS232C - 5!= Gradiente interface (brazilie) - 6!= Multichannel ASCII compatible - Versies met een "!" zijn nog niet gemaakt, maar - er is een kans dat dezen er nog zullen komen. - - - L A A T S T E O P M E R K I N G E N - - Deze driver is nog niet compleet uitontwikkeld, dus er - zullen nog wel uitbreidingen komen. Deze uitbreidingen - zullen compatible blijven met oudere versies van de driver. - Ik ben bezig met een terminal te schrijven voor deze driver, - genaamd ERIX, deze heeft minimaal een MSX2 nodig met 64 Kb, - en minimaal MSX-DOS1. ERIX ondersteund Xmodem(1k) en Ymodem, - zowel up/download. De schermuitvoer is behoorlijk snel, en - emuleert momenteel VT-52, ANSI wordt nog gemaakt. - De driver heeft geen bezwaar tegen een turbo-R op R800-Dram - mode, maar werkt natuurlijk ook goed op een 3.58 Mhz Z80. - Om steeds de nieuwste versie van ERIX en de drivers te - bemachtigen, kun je naar The Games BBS (04120-40358) bellen, - en daar de nieuwste versies te zoeken. - Als je nog aan- en/of opmerkingen hebt, laat dan een - berichtje voor me achter in MSX-net (inlogpunt bv. - RoefSoft), of stuur een berichtje naar me in The Games BBS. - Gewoon onder de naam : - Erik Maas diff --git a/sunrise_special/7/Gestructureerd ML deel 3.md b/sunrise_special/7/Gestructureerd ML deel 3.md deleted file mode 100644 index 3f4a1b6..0000000 --- a/sunrise_special/7/Gestructureerd ML deel 3.md +++ /dev/null @@ -1,129 +0,0 @@ - G E S T R U C T U R E E R D M L ( 3 ) - - - Een kort deel deze keer, zoveel valt er nu ook weer niet - over dit onderwerp te vertellen zonder op details in te - gaan, en daar hebben we al de rubriek ML technieken. - - Het is een beetje afhankelijk van het project waar je mee - bezig bent, maar zelf geef ik duidelijk programmeren - voorrang boven een paar bytes minder code of een paar - klokpulsen minder. Wat ik bedoel is: als ik kan kiezen - tussen een duidelijke oplossing van 10 bytes en 30 - klokpulsen en een minder duidelijke oplossing van 8 bytes en - 25 klokpulsen, dan zal ik toch de duidelijke oplossing - kiezen. Als ik om snelheids- of ruimteredenen toch de minder - duidelijke oplossing moet kiezen, zal ik extra commentaar - erbij zetten. - - Even een paar voorbeelden. Als er aan het eind van een - routine het volgende staat: - - CALL AndereRoutine - RET - - Scheelt het 1 byte en 18 klokpulsen om dit te vervangen door - - JP AndereRoutine - - Dit is echter niet het meest duidelijk, want het einde van - een routine is RET en niet JP. Nog een voorbeeld: - - CP #FF - JR Z,Label - - Hier kan de CP #FF worden vervangen door een INC A. Dat - scheelt 1 byte en 3 klokpulsen. Maar het is veel - onduidelijker, we willen immers kijken of A gelijk is aan - #FF en we willen A helemaal niet verhogen. (De CP #FF kan - dan ook niet door INC A worden vervangen als je de waarde - van A daarna nog nodig hebt.) Als je dit toch gebruikt omdat - je zeer krap zit qua tijd en/of geheugen, doe het dan zo: - - INC A ; CP #FF - JR Z,Label - - Zo kun je in ieder geval nog aan het commentaar zien wat de - bedoeling was. Zelf gebruik ik wel AND A in plaats van CP 0, - maar dat is iets anders omdat AND A alleen die betekenis - heeft (tenminste voor mij), terwijl je INC A ook heel vaak - gebruikt om gewoon A te verhogen. De carry wissen doe ik - trouwens met OR A. Dat kan ook met SCF; CCF maar dat is veel - langzamer en neemt meer bytes in beslag. AND A zou ook - kunnen, maar ik heb met mezelf afgesproken dat ik AND A - gebruik voor CP 0 en OR A om de carry te wissen. Zo kan ik - ��n oogopslag zien wat een instructie betekent. - - - J R O F J P ? - - JP is sneller dan JR maar neemt ��n byte meer in beslag. - Bovendien is een voorwaardelijke JR sneller als er niet - wordt gesprongen. Wanneer gebruik je JR en wanneer JP? - - Ik gebruik zoveel mogelijk JR voor sprongen binnen ��n - routine. Zo kun je meteen zien dat het een sprong binnen - dezelfde routine is. Soms kan dat niet omdat de - sprongafstand te groot is, maar dat is vaak een teken dat de - routine te lang is en in deelproblemen moet worden - opgesplitst. Dit is echter zeker geen wet van meden en - perzen. JP is bij mij gereserveerd voor sprongen naar een - andere routine, al moet je dat alleen in speciale gevallen - doen. Want voor dat je het weet heb je een onleesbaar stuk - spaghetti. Verder ondersteunt JP meer voorwaardelijke - sprongen (P, M, PE, PO) dan JR, maar die gebruik je vrij - weinig. - - Voor degenen die in tijd- of ruimtenood zitten nog even de - gegevens van JP en JR: - - klokcycli: bytes: - - JP 11 3 - JR 13 (8) 2 - - De tijd tussen haakjes bij JR geeft aan hoe lang het duurt - als er niet wordt gesprongen bij een voorwaardelijke sprong. - Het is overigens logisch dat JR langer duurt dan JP, omdat - bij JP de Program Counter gewoon met het adres geladen kan - worden, terwijl bij JR iets bij de Program Counter moet - worden opgeteld. - - - N O G Z O I E T S - - Stel je wilt wachten tot bit 0 van I/O poort #65 laag wordt - (wachten op CE bij V9990). Dan programmeer ik dat zo: - - WaitCE: IN A,(#65) - BIT 0,A - JR NZ,WaitCE - - Zo kun je precies zien wat er gebeurt. Ik geef toe dat het - sneller is om onderstaande variant te gebruiken, maar hier - is het minder duidelijk: - - WaitCE: IN A,(#65) - RRCA - JR C,WaitCE - - Bit 0 wordt namelijk in de carry geschoven door RRCA. Als je - dat er in commentaar achter zet is het natuurlijk al weer - een stuk duidelijker. Het nadeel van deze methode is dat het - alleen bij bit 0 werkt, bij een ander bit moet je toch weer - op BIT n,x terugvallen. - - - S N E L H E I D O F N E T H E I D ? - - Nogmaals, het hangt af van het soort programma hoeveel - aandacht je aan de netheid KUNT besteden. Want als je het - onderste uit de kast wilt halen dan kan dat alleen maar door - een tabel met klokcycli bij de hand te houden en overal de - snelste oplossing voor te kiezen. Maar bij veel programma's - is dat onzin en dan is het belangrijker om de netheid in het - hoog te houden, zodat je eigen sources straks tenminste nog - kunt begrijpen. Gebruik in ieder geval commentaar bij - truukjes die je niet al veel vaker hebt gebruikt. - - Stefan Boer diff --git a/sunrise_special/7/Harddisks op MSX.md b/sunrise_special/7/Harddisks op MSX.md deleted file mode 100644 index defe01f..0000000 --- a/sunrise_special/7/Harddisks op MSX.md +++ /dev/null @@ -1,336 +0,0 @@ - H A R D D I S K S O P M S X - - - - D E M O G E L I J K H E D E N - - Al in 1990 was de eerste harddisk interface voor MSX - verkrijgbaar. Tot nu toe is er niet veel aandacht besteed - aan MSX harddisks. Dit is voor verandering vatbaar, nu - steeds meer mensen het genot van een harddisk aan de MSX - ervaren. - - MSX is lang verstoken gebleven van harddisks. Philips is wel - al heel lang geleden bezig geweest met een SCSI interface - voor MSX, maar die is nooit uitgekomen. Tot 1990 heeft het - moeten duren voor de eerste interface voor het gewone - publiek te krijgen was. Althans, voor mensen met genoeg - geld! De eerste complete harddisks waren vrij prijzig. - - In een paar jaar is dat echter grondig veranderd. De prijzen - van SCSI interfaces voor MSX zijn een stuk redelijker - geworden, en bovenal, SCSI harddisks zelf zijn een stuk - goedkoper geworden! Dit is voornamelijk te danken aan het - feit dat mensen met andere computers, zoals Apple en Atari, - overstapten op HD's met een veel grotere inhoud. Een 40 MB - HD kost nu toch al gauw minder dan 200 gulden op de - tweedehandsmarkt. - - - D E I N T E R F A C E S - - De eerste interface was van HSH. Deze interface is de enige - die ook onder MSX-DOS1 werkt. Het nut hiervan is echter niet - al te groot. Het werken met subdirectory's is echt een - vereiste voor een HD-gebruiker. - - De HSH interface kan 6 partities (zie verderop) aan, en - beschikt over netwerkmogelijkheden. - - Toen kreeg ook MK een vinger in de HD-pap. MK bracht een - interface op de markt met de mogelijkheid om 4 partities aan - te sturen, die ook weer de mogelijkheid had met SCSI - netwerken om te gaan. - - - G O U D A 'S G L O R I E - - Van MAK of Green komt de interface die later door MSX Club - Gouda geadopteerd is. Deze kan 4 partities gebruiken, en - bezit geen netwerkmogelijkheden. - - Sinds begin dit jaar is er echter een nieuwe Gouda interface - leverbaar. Het gaat hierbij om een flink verbeterd HSH - ontwerp. De interface heeft netwerkmogelijkheden, en op een - turbo R is het ding supersnel! - - - P A R T I T I E S - - Al een aantal malen heb ik het woord "partitie" gebruikt. - Als een HD 4 partities heeft, betekent dit dat de HD voor de - computer uit 4 drives bestaat: A:, B:, C: en D:. Omdat een - drive maximaal 32 MB kan zijn, kan een interface met 4 - partities dus ook ten hoogste 128 MB aansturen! - - Het gebruik van 6 partities is niet zo handig, omdat je - meestal minstens over EEN drive en een RAMdisk wilt - beschikken. Een beperking van DOS2 is dat je maar 8 drives - kunt gebruiken. Ook een beperking is dat je geen RAMdisk - kunt aanmaken als je al 8 drives hebt. In het geval van 6 - partities en 2 drives (ook een virtueel drive telt mee - zijn), kun je dus geen RAMdisk meer aanmaken. - - - H A R D D I S K Z E L F - - Voordat je de aanschaf van een bepaalde harddisk overweegt, - is het belangrijk even na te denken over wat je erop gaat - zetten. Als je heel veel plaatjes, spellen en muziek erop - gaat zetten, is 100 MB wel handig. - - Als je echter zuinig met de ruimte omgaat, en alleen echt - handige dingen op je HD wilt zetten, is 20 MB al meer dan - genoeg. - - Voor de meeste MSX'ers zal een harddisk tussen de 30 en 40 - MB wel voldoende zijn. Alles samen moet in dat geval wel - voor 400 gulden te verkrijgen zijn. Ongeveer � 200,- voor de - harddisk, � 150,- voor de interface en � 50,- voor voeding, - kastje en kabels. [Nvdr. Als je een turbo R hebt is de - aanschaf van een HG-interface voor � 239,- zonder meer het - geld waard.] - - - H D I N D E L E N - - Als je in het bezit bent van je harddisk, is het belangrijk - om niet gewoon alles wat je hebt erop te gooien - oftewel - kopi�ren - maar een beetje overdacht te werk te gaan. Dit om - ervoor te zorgen dat je na een tijdje door de bomen het bos - niet meer ziet, en om de haverklap utility's als FileFind - nodig hebt om een bepaalde file uit een wirwar van - subdirectory's terug te vinden. - - - N O G M A A L S : P A R T I T I E S - - Om maar te beginnen bij het begin: je moet de harddisk - opdelen in partities. Dit wordt ook wel "high level - formatteren" genoemd. Meestal is de harddisk al "low level" - geformatteerd. - - Bij het low level formatteren wordt de disk echt - leeggemaakt. Dit neemt dan ook veel tijd in beslag. High - level formatteren houdt het indelen van de HD in partities - in, en het daarbij opgeven van bepaalde belangrijke - gegevens, zoals de FAT-grootte, de grootte van de - rootdirectory, etc. - - - C L U S T E R G R O O T T E - - Je kunt, als je een harddisk kleiner dan of gelijk aan 32 MB - hebt, gewoon ��n partitie aanmaken. Maar dit is niet erg - slim. Je krijgt dan vrij grote clusters, soms zelfs van 32 - kB. Hierdoor wordt je harddisk niet erg snel, en is hij ook - vrij snel gevuld. - - Een programmaatje van 10 bytes kost bij een clustergrootte - van 32 kB nl. 32 kB! Bij clusters van 1 kB echter nog maar 1 - kB. - - Het is dus verstandig om een kleine A: partitie aan te maken - met daarop allerlei (kleine) programma's die je vaak - gebruikt. Ik heb zelf gekozen voor 4 MB. Als je dan de FAT - op 12 sectoren zet, heb je clusters van 1 kB. - - - F A T - G R O O T T E - - Je kunt het beste altijd een FAT van 12 sectoren nemen, dan - is de clustergrootte het kleinst. - - Nu de eerste partitie klein is, kun je de volgende - partitie(s) natuurlijk wel zo groot mogelijk maken. Als je - het �cht maximaal neemt, krijg je clusters van minimaal 32 - kB. Ik heb daarom even gekeken of dit niet beter kon. En het - KON beter. Als je als grootte 32686 kB neemt (bij FDISK van - MK), krijg je met een FAT van 12 sectoren clusters van 16 - kB, en bij 1 kB meer is dit al 32 kB. [Nvdr. Bij de HG - interface krijg je maximaal clusters van 8 kB.] - - - R O O T - D I R - - Je moet voorkomen dat er veel files in de rootdirectory - komen te staan. Je kunt het beste alleen COMMAND2.COM, - MSXDOS2.SYS, AUTOEXEC.BAT en REBOOT.BAT in de root laten - staan. Dit is niet alleen voor de overzichtelijkheid, maar - het komt ook de snelheid ten goede. Bij het opstarten worden - de juiste files dan meteen gevonden. - - De rootdirs van de andere partities kun je het beste - helemaal leeg laten. Daar mogen eigenlijk alleen maar - subdirectory's in staan. - - Bij FDISK kun je daarom ook het beste de dirgrootte op 64 - bestanden zetten, omdat dit de kleinste grootte is. - - - S U B D I R S - - Zoals gezegd komen op A: programma's die vaak gebruikt - worden. Ik heb zelf gekozen voor de volgende indeling van A: - - A:\ - 2RAMDISK - BATCH - MEMMAN - TSRS - UTILS - BASIC - CRUNCH - DOS2TOOL - ML - TURBOR - - In 2RAMDISK staan vaakgebruikte programma's die door - AUTOEXEC.BAT naar de RAMdisk gekopieerd worden. (Na een - reset wordt mijn RAMdisk gered door RRAMDISK, dus dit kost - alleen tijd als ik de computer aanzet.) - - BATCH bevat alle batchfiles die ik gebruik, MEMMAN allerlei - MemMan files, TSRS alle MemMan TSR's, en UTILS en zijn - subdirectory's alle verdere utility's. - - Voor de verdere indeling van UTILS heb ik gekozen om - bepaalde utility's nog enigszins makkelijk terug te kunnen - vinden. - - Wat allemaal op mijn andere 3 partities staat is verder niet - zo heel interessant. Maar misschien wel belangrijk is de tip - om ervoor te zorgen dat de rootdirectory niet al te vol - wordt gezet met subdirectory's. - - Als je werkt met algemene directory's, komt dat de - overzichtelijkheid zeker niet ten slechte. Ik heb zelf zo - subdirectory's met namen als MUSIC, TEKST en PROG. Deze - directory's bevatten zelf geen enkele file, maar slechts - subdirs. - - - H A R D D I S K U T I L S - - Voor harddiskgebruik zijn er gelukkig al een aantal - utility's gemaakt. Zo bestaat het programma FileFind, zelfs - in drie verschillende versies. Maar die van Ramon van der - Winkel is wel het beste - d.w.z. snelste en kleinste. Dit - programma staat op de disk. - - - T O - - Zodra je harddisk een beetje vol begint te raken, kost het - veranderen van directory al snel redelijk wat typewerk. - Gelukkig is hiervoor een oplossing. - - De meeste PC'ers kennen het programmaatje TO al, eventueel - onder de naam NCD (Norton Change Dir). Daar werkt het echter - wel iets iets anders. TO UT, bijvoorbeeld, geeft een - overzicht van alle subdirectory's die het stukje "UT" in de - naam hebben zitten. Bij mij staan er dan onder andere UTILS - en OUTDOOR bij. - - TO is een public domain programmaatje van C.P.U. dat ook op - deze disk te vinden is. - - Bij TO UT komt het volgende op mijn scherm: - - A - A:\MEMMAN\TSRS - B - C:\DIVERSEN\FONTS - C - D:\TEMP\KIER\BACKATSU - - Als ik dan op A druk, wordt er meteen naar de directory - A:\MEMMAN\TSRS gesprongen. - - Voordat TO kan werken moet het echter eerst een overzicht - aanmaken van alle subdirectory's - telkens alle dirs - opzoeken zou veel te traag gaan. Met het environment item - TO_PATH geef je aan waar dit overzicht komt te staan. Met de - optie /S (scan) achter TO geef je aan dat er een overzicht - moet worden aangemaakt, dat onder de naam TO.LST in de door - TO_PATH aangeduide dir komt te staan. - - - M E E R D E R E D R I V E S - - TO kan ook met meerdere drives werken. Gelukkig wel, anders - moest je nog steeds weten op welke drive de bepaalde dir - staat. Het environment item TO_DRIVES geeft aan welke drives - gebruikt worden door TO. Zo bevat mijn AUTOEXEC.BAT het - commando "SET TO_DRIVES=ABCD". - - Als je er iets aan de samenstelling van de subdirectory's - verandert, zou je eigenlijk weer opnieuw moeten scannen. - Gelukkig heeft Fokke Post (de maker) hier rekening mee - gehouden. De volgende opties zijn hiervoor bedoeld: - - /M : Maakt een nieuwe directory aan. Komt overeen met MKDIR - of MD. - /D : Wist de directory. Komt overeen met RD of RMDIR. - /C : Maakt een nieuwe directory aan, en ga er gelijk - naartoe. Dus eigenlijk zijn twee commando's - samengevoegd: MD en CD: MCD! - /R : Hernoemt een directory. Staat gelijk met RNDIR. - /V : Verplaatst een hele directory naar (in) een andere - directory. Hiervoor had COMMAND2.COM nog geen commando, - maar MVDIR zou het wel geheten hebben. - - - C O M M A N D 2 A A N P A S S E N - - Bij TO v1.52 zat een programmaatje INSTALL.COM dat o.a. - COMMAND2.COM kan aanpassen. Dan worden de commando's die - beter via TO gedaan kunnen worden verwijderd uit het - vocabulaire van COMMAND2 (MD, CD, RNDIR enz.). Deze - commando's worden dan vervangen door batchfiles. - - Dit is heel handig, maar het is jammer dat het mijn - COMMAND2.COM helemaal verneukte - excusez le mot. Ik heb - toen met een foefje (opstarten met HD aan, als computer - zoekt naar MSXDOS2.SYS HD uitzetten, en even later weer - aanzetten) COMMAND2.COM weer moeten kopi�ren van een gewone - disk. - - Gelukkig is de programmeur op de hoogte gesteld, en bevat - bestaat er nu een prima werkende INSTALL. De moraal van dit - verhaal is echter: probeer vitale bestanden (eigenlijk - alleen COMMAND2.COM en MSXDOS2.SYS) eerst uit op gewone - diskettes of op de RAMdisk voordat je ze kopieert naar de - harddisk. - - [Nvdr. Het is het verstandigste om op de A: partitie alleen - utility's en dergelijke te zetten die je ook op disk heb - staan, dus geen eigen teksten, sources etc. Want in het - geval de A: partitie echt verrot raakt (bijvoorbeeld dat - MSXDOS2.SYS of COMMAND2.COM vastslaat), is de enige - oplossing om weer in je HD te komen de A: partitie opnieuw - installeren, en dan ben je alles kwijt wat erin stond. Dat - is met utility's die je zo weer van disk kunt kopi�ren geen - probleem, maar met sources, teksten etc. waarvan je geen - backup hebt een ramp! Ik spreek uit ervaring, maar bij mij - liep het gelukkig nog net goed af.] - - - V E R D E R E F U N C T I E S - - TO kan ook nog heel snel terugspringen in directory's. TO .. - werkt hetzelfde als CD .., maar TO kan ook nog meer puntjes - verwerken. Drie puntjes betekent twee directory's terug, - enz.. Met TO -5 ga je echter ook meteen 5 directory's terug - (staat dus gelijk aan ......). - - Bij het aanmaken en springen naar directory's kun je overal - de optie /H gebruiken om hidden directory's te nemen. - - Met de optie /N kun je aanduiden dat TO gewoon de directory - moet nemen die hij het eerste vindt. Zo kun je lijsten van 3 - schermen (bijv. bij TO S) voorkomen. - - Van dezelfde programmeur komt ook het programmaatje - TREE.COM. Hiermee kun je een overzicht van de directory's - van een bepaalde drive krijgen. Het werkt natuurlijk met de - door TO.COM aangemaakte file TO.LST. - - Kasper Souren diff --git a/sunrise_special/7/Interfacing RS232.md b/sunrise_special/7/Interfacing RS232.md deleted file mode 100644 index 8693fa8..0000000 --- a/sunrise_special/7/Interfacing RS232.md +++ /dev/null @@ -1,188 +0,0 @@ - I N T E R F A C I N G ( R S 2 3 2 C ) - - - - W A A R O M E E N S T A N D A A R D ? - - Om goede interfacing te kunnen doen, dwz. data uit - wissellen, is het noodzakelijk dat de verschillende systemen - die dat moeten kunnen doen compatible zijn. Hiervoor zijn - afspraken nodig. - - Deze afspraken houden het volgende in : - - Hoe moet de verbinding gerealiseerd worden? - - Wat betekenen deze verbindingen? - - Wat zijn de defenities van de signalen die deze - verbindingen voeren? - - - W I E M A A K T D E A F S P R A K E N ? - - De afspraken die we nu gebruiken met de RS232C gedefinieerd - door EIA (Electronic Industries Association) zijn afgeleid - van de V.24 en V.28 aanbeveling van het CCITT (Committee - Consultative International de Telegraphique et - Telephonique), een organisatie die standariserings normen - vaststeld. V.24 worden de functies van de pennen - gedefinieerd, terwijl V.28 de spanningsnivo's definieren. - - - W A T I S V . 2 8 ? - - Om data over een draad te kunnen verplaatsen, hebben we - duidelijke afspraken nodig over de nivo's. Zo hoeven we met - de computer maar een "0" of een "1" over de lijn te krijgen, - of in geval van controle signalen een "on"/"off". - Nu is de afspraak gemaakt dat met een negatieve spanning we - een "1" hebben, of in het geval van een control signaal een - "off". De maximale spanningen die gebruikt mogen worden zijn - -25 en +25 Volt. Het gebied tussen -3 en +3 Volt is niet - gedefinieerd. - Dus zenden we een "1"(off) over, dan moet de spanning tussen - -25 en -3 Volt liggen. - De reden dat het gebied tussen -3 en +3 volt niet - gedefinieerd is, ligt aan het feit dat je hardware nodig - hebt die de lijn meet, om die hardware simpel te kunnen - houden, moeten we een hogere spanning sturen dan in feite - nodig is. - Meestal wordt met -12 en +12 gestuurd. - - - W A T I S V . 2 4 ? - - Deze afspraken houden in wat de functies van diverse - signalen zijn. - - Hieronder een overzicht van de defenities van de pinnen bij - een 25 pin's sub-D aansluiting. (Die op de meeste RS232C - interfaces zit) - - Type Pin MNEMONIC Uitleg In/Out - - GROUND 7 GND Ground - - - DATA 2 TMD,TxD TransMit Data O - 3 RCD,RxD ReCeive Data I - - CONTROL 4 RTS Ready To Send O - and 5 RFS,CTS Clear To Send I - STATUS 6 DSR Data Set Ready I - 20 DTR Data Terminal Ready O - 8 DCD Data Carrier Detect I - 23 DRS Data Signal rate Selector O - 22 CIN Calling Indicatior I - 11 STF Select Transmit Frequency O - - CLOCK 24 TSET,TxC Transmitter Signal Element Timing O - 15 TSET,TxC Transmitter Signal Element Timing I - 17 RSET,RxC Receiver Signal Element Timing I - - BACK- 14 TMD,TxD TransMit backward channel Data O - WARD 16 RCD,RxD ReCeive backward channel Data I - CHANNEL 19 RTS Ready To Send backward channel O - 13 RFS,CTS Clear To Send backward channel I - 12 DCD backward channel DCD I - - TEST 21 RIL Loopback test O - 18 LL Local Loopback O - 25 TI Test Indicator I - - - U I T L E G S I G N A L E N - - D A T A - - Via TMD wordt de data verzonden, de data moet serieel - verstuurd worden, dit heeft als voordeel dat we maar 1 - lijn nodig hebben. Deze methode heeft echter wel als - nadeel dat de doorvoersnelheid beperkt is. - Nog een probleem met seriele interfacing is dat de - ontvanger dit signaal weer netjes in mekaar kan zetten tot - de oorspronkelijke data. Hiervoor moeten we een methode - verzinnen die redelijk snel kan zijn, zonder al te veel - moeilijkheden. De RS232C communicatie die we gebruiken - heeft een redelijk simpele methode om de data te - versturen. Er wordt aangenomen dat de ontvanger weet op - welke snelheid er verzonden wordt, en stelt de - ontvangstklok in op die snelheid. De zender wil op een - gegeven moment iets overzenden. Om de ontvanger opmerkzaam - hierop te maken (triggeren) wordt het signaal wat normaal - gesproken in rusttoestang hoog is, laag gemaakt. Dit wordt - gedaan voor 1 gehele periode van de zend frequentie. - Hierna wordt op dezelfde snelheid de data overgestuurd, - ook weer geinverteerd. Afhankelijk van het protocol kan - hier achter die data nog een parity bit komen. Hierachter - worden nog 1 of 2 stopbits geplaatst. Meestal wordt er - voor 1 stopbit gekozen voor een iets hogere doorvoer. - Deze methode van zenden is A-SYNCHROON. - Via RCD wordt op dezelde methode data ontvangen. - - - C O N T R O L / S T A T U S - - Ik bespreek alleen de meest toegepaste signalen, enkelen - die niet gebruik worden op de MSX, en ik dus helaas ook - niet ken, bespreek ik niet. - - RTS is ervoor om te zorgen dat je aan de zender door kunt - geven dat je op dat moment geen data meer kunt/wilt - ontvangen. De zender hoort hier dan rekening mee te - houden. - Door RFS af te scannen tijdens het zenden, weet de zender - dat deze op een gegeven moment op moet houden, als de - ontvanger dit wil. - Deze RTS/RFS worden in sommige oude communicatie - programma's niet gebruikt, dan wordt er Xon/Xoff handshake - gebruikt, wat inhoud dat de zender reageert op bepaalde - karaktercodes door te starten of stoppen met zenden. - Met DSR geeft een device aan dat ie actief is, dus dat er - data naartoe verzonden mag worden. - DTR is het signaal wat je afgeeft, om aan te duiden dat je - actief bent, verwar dit niet met RTS, want RTS werkt - alleen als DTR geldig is. - Met DCD heeft de tegenpartij aan dat ie herkent heeft dat - er data komt, een modem kan hier bv. mee aangeven dat er - een verbinding is met een ander modem. - CIN is een signaal wat de tegenpartij, met deze toepassing - meestal een modem, aan dat er een oproep is. - TSET en RSET zijn klokfrequenties voor ontvangen/zenden - van data. - Het complete backward channel werkt zoals de equivalente - functies hierboven. - - - D E P R A K T I J K - - In de praktijk zijn meestal niet alle functies opgenomen in - de interface. Zo heb ik nog nooit een MSX RS232C interface - gezien met de TEST functies. Een MSX RS232C interface met - een werkende backward channel is ook ver te zoeken, maar de - Philips NMS121x is er wel op voorbereid. Dit vereist een - andere kabel, met een andere aansluiting IN de interface. - Heeft wel als nadeel dat je dan maar 1 aansluiting kunt - gebruiken, daar channel B dan ook op de aansluiting van - channel A komt. Wat ik ook nog niet gezien heb op de MSX - RS232C interfaces is de rate/frequency selector. - - Even een korte opsomming over "tekortkomingen" op twee MSX - RS232C interfaces. Deze tekortkomingen zijn in feite niet - echt nodig, en worden op andere systemen ook niet gebruikt, - bij mijn weten. - - - De NMS121x interfaces : - - Niet ondersteund : DRS, STF, RIL, LL, TI - Op voorbereid : complete backward channel - - - De SONY HBI1 RS232C interface (MSX standaard) : - - Niet ondersteund : DRS, STF, RIL, LL, TI, TSET in, TSET out, - RSET, complete backward channel - - Deze functies zullen ook niet op andere standaard MSX-RS232C - interfaces opgenomen zijn, simpelweg omdat deze functies - niet gedefinieerd zijn door ASCII. - - Erik Maas diff --git a/sunrise_special/7/ML Technieken.md b/sunrise_special/7/ML Technieken.md deleted file mode 100644 index 9bf65c2..0000000 --- a/sunrise_special/7/ML Technieken.md +++ /dev/null @@ -1,481 +0,0 @@ - M L T E C H I E K E N ( 1 ) - - - Het lijkt mij een goed idee om naast de cursus BASIC - technieken op Sunrise Magazine een cursus ML technieken te - starten op de Special. Ook dit is geen programmeercursus - maar een verzameling tips en truuks en manieren hoe je iets - het beste kunt aanpakken. Ik ben overigens niet van plan om - deze cursus alleen te schrijven, maar zal zeker een aantal - ML programmeurs met meer ervaring vragen hun geheimen prijs - te geven in deze rubriek. Deze keer een paar simpele - problemen waar beginners tegenaan zullen lopen. - - Ik zal bij vergelijking van routines tellingen van klokcycli - en bytes geven, bij de klokcycli ga ik uit van een Z80. Over - het algemeen zal een routine die sneller is op de Z80 ook - sneller zijn op de R800, maar dit is geen wet van Meden en - Perzen. - - - B Y T E U I T T A B E L H A L E N - - Stel je hebt een tabel en je hebt een waarde in A die - aangeeft de hoeveelste byte van de tabel je wilt hebben. - Deze byte moet uiteindelijk in A terechtkomen. Hiervoor moet - je het adres in de tabel uitrekenen, het liefst zou je dat - doen met - - LD HL,Tabel - ADD HL,A - LD A,(HL) - - maar de instructie ADD HL,A bestaat natuurlijk niet, want je - kunt geen 8 bits register bij een 16 bits register optellen. - We zullen de instructie ADD HL,A dus zelf moeten maken. Er - zijn op z'n minst twee oplossingen mogelijk. De eerste is - degene die ik meestal gebruik: - - klokcycli bytes - - LD E,A 5 1 - LD D,0 8 2 - LD HL,Tabel 11 3 - ADD HL,DE 12 1 - LD A,(HL) 8 1 - ---- --- - 44 8 - - De eerste twee instructies betekenen LD DE,A. Vervolgens - wordt DE bij HL opgeteld en de byte uit de tabel gelezen. - Het nadeel hiervan is dat je het DE register (of eventueel - het BC register) gebruikt. De volgende oplossing doet dat - niet: - - klokcycli bytes - - LD HL,Tabel 11 3 - ADD A,L 5 1 - LD L,A 5 1 - LD A,0 8 2 - ADC A,H 5 1 - LD H,A 5 1 - LD A,(HL) 8 1 - ---- --- - 47 10 - - - ADD A,L; LD L,A is een substituut voor ADD L,A (dat niet - bestaat). Vervolgens moet nog de carry bij H worden opgeteld - (LD A,0; ADC A,H; LD H,A). Het voordeel is dat het DE (of - BC) register niet wordt gebruikt, maar deze routine is iets - trager (3 klokcylci is 0.84 microseconde, niet echt een - verschil dat je snel zult merken) en wat erger is: 2 bytes - langer. Ik heb vaak problemen dat mijn code te groot wordt, - en ik heb daarom een grote voorkeur voor kortere - oplossingen, zelfs als dat een paar klokcycli trager is. - - Er is nog een alternatief dat sterk op de vorige lijkt, hier - wordt alleen een andere manier gekozen om de carry bij H op - te tellen: - - klokcycli bytes - - LD HL,Tabel 11 3 - ADD A,L 5 1 - LD L,A 5 1 - JR NC,Label 13/8 2 - INC H 0 /5 1 - Label: LD A,(HL) 8 1 - ---- --- - 42 9 - - Het grappige van deze routine is dat hij ondanks de - voorwaardelijke sprong altijd even snel is, dit komt omdat - als hij springt (13 klokcycli) hij de INC H niet doet, en - als hij niet springt (8 klokcycli) hij de INC H (5 - klokcycli) er nog bij doet, waardoor de LD A,0; ADD A,H; LD - H,A constructie van de vorige oplossing (18 klokcycli, 4 - bytes) dus wordt vervangen door 13 klokcycli en 3 bytes. - Vandaar de 5 klokcycli en 1 byte winst. - - Deze oplossing is dus sneller dan de oplossing met DE (44 - klokcycli), maar het kost weer een byte meer (9 in plaats - van 8). Als je ruim in je geheugen zit en die ene byte extra - je geen bal kan schelen is deze oplossing dus het beste - (lees: snelste), en als je het DE register al voor iets - anders in gebruik hebt is het zeker de beste. Maar als elke - byte telt geef ik de voorkeur aan de eerste oplossing. Nog - een nadeel van deze oplossing is dat het een extra label - geeft en of dat een nadeel is is vooral afhankelijk van de - assembler die je gebruikt. - - Tot slot nog even hoe het niet moet: - - klokcycli bytes - - LD IX,Tabel 15 4 - LD (Poke+2),A 14 3 - Poke: LD A,(IX+0) 20 3 - ---- --- - 49 10 - - Dit is verreweg de meest lelijke oplossing die ik kan - bedenken. Hij is ook nog eens de traagste en net zo lang als - de langste oplossing tot nu toe. Bovendien doe je iets dat - eigenlijk helemaal niet mag (het kan niet eens als je - programma op ROM wordt gezet!), namelijk het poken in je - code. Indexregisters zijn traag maar erg handig bij tabellen - met een variabel beginadres waaruit je bytes op vaste - plaatsen wilt lezen. (Er zijn namelijk geen LD A,(IX+B) - instructies of zoiets, het is altijd LD A,(IX+n), waarbij n - een constante tussen -128 en +127 is.) Ik heb daar al eens - een tekst over geschreven op de Special. Hier is het precies - andersom: een vast beginadres en een variabele plaats. Dat - doe je dus NIET met indexregisters. Het ziet er in je source - erg kort uit (3 regels, terwijl de andere oplossingen - respectievelijk 5, 6 en 7 regels in beslag nemen), maar - instructies met IX en IY zijn gewoon erg traag. - - Er is nog ��n truuk die je kunt gebruiken als je echt - maximale snelheid nodig hebt: zorg dat je tabel op een adres - begint waarvan de lowbyte gelijk is aan 0! Dus bijvoorbeeld: - - Tabel: EQU #D000 - - klokcycli: bytes: - - LD H,#D0 8 2 - LD L,A 5 1 - LD A,(HL) 8 1 - --- --- - 21 4 - - Deze routine is twee keer zo snel en twee keer zo kort als - de snelste en kortste routines die we tot nu toe - tegenkwamen, maar dat komt door de speciale eis die aan de - tabel wordt gesteld. Op zich heel mooi maar vaak onhandig om - toe te passen, zeker als je veel tabellen hebt. Toch is dit - zeker iets wat je in gedachten moet houden voor als je eens - in snelheidsnood zit. - - - J U M P T A B E L - - Iets wat veel met het vorige onderwerp te maken heeft is een - jumptabel. Vergelijk dit maar met ON A GOTO in BASIC. Altijd - een zeer snelle methode om een keuze uit een redelijk groot - aantal alternatieven te maken. Bij slechts een paar - alternatieven is CP x; JP Z,y korter en sneller. - - Ik heb hiervoor altijd een standaardroutine met de naam - Jump. In A staat het nummer van de gewenste sprong en in HL - het begin van de jumptabel. Die routine is als volgt: - - klokcycli: bytes: - - Jump: DEC A 5 1 - ADD A,A 5 1 - LD E,A 5 1 - LD D,0 8 2 - ADD HL,DE 12 1 - LD E,(HL) 8 1 - INC HL 7 1 - LD D,(HL) 8 1 - EX DE,HL 5 1 - JP (HL) 5 1 - ---- --- - 68 11 - - De DEC A is nodig omdat het eerste adres in de tabel - natuurlijk offset 0 heeft. Daarna verdubbelen we A omdat een - adres 2 bytes lang is. Daarna tellen we A bij HL op via DE, - omdat we net hebben gezien dat dat de korste oplossing is en - we DE sowieso nodig hebben. Een instructie LD DE,(HL) - bestaat helaas niet dus doen we dat met LD E,(HL); INC HL; - LD D,(HL). Tenslotte verwisselen we DE en HL (want het adres - waarnaar we moeten springen staat in DE en moet in HL - terecht komen) en springen we naar dat adres toe. Volgens - mij is er geen betere oplossing hiervoor, de eis dat L - gelijk moet zijn aan 0 (zodat we alleen maar LD L,A hoeven - te doen in plaats van LD E,A; LD D,0; ADD HL,DE) is hier - zeer onhandig. - - - Deze tekst wordt vervolgd in de volgende submenu-optie - - - - - - Dit is het tweede gedeelte - - - M L T E C H N I E K E N ( 1 ) - - - C O M P A R E - - Veel beginnende programmeurs hebben moeite met de instructie - CP, wat een afkorting is voor ComPare. Eigenlijk is het - helemaal niet moeilijk als je maar weet hoe het werkt. - - De volgende CP instructies zijn mogelijk: - - klokcycli: bytes: - - CP (HL) 8 1 - CP (IX+n) 20 3 - CP (IY+n) 20 3 - CP A 5 1 - CP B 5 1 - CP C 5 1 - CP D 5 1 - CP E 5 1 - CP H 5 1 - CP L 5 1 - CP n 8 2 - - Bij een CP x instructie zal de Z80 de vlaggen zo zetten als - ook bij een SUB x instructie gebeurt, zonder de waarde van A - te veranderen. Er zijn dus drie gevallen mogelijk: - - - als x kleiner is dan A dan komt er geen carry want je kunt - x gewoon van A aftrekken zonder dat je een negatieve - uitkomst krijgt - - als x gelijk is aan A dan komt er een zero want A-x is dan - gelijk aan 0, er is GEEN carry want er is nog net geen - negatieve uitkomst - - als x groter is dan A dan komt er een carry want er is een - nieuwe uitkomst - - Samengevat: - - A >= x NC - A < x C - A = x Z - A <> x NZ - - Je hoeft dit niet uit je hoofd te kennen, je kunt gewoon - beredeneren wat er met de zero- en carryflag gebeurt als je - x van A af zou trekken. - - Als je zoals ik in het vorige onderdeel al opmerkte - slechts weinig alternatieven hebt, dan is het sneller om de - volgende constructie toe te passen: - - klokcycli: bytes: - - CP 1 8 2 - JR Z,Keuze1 8/13 2 - CP 2 8 2 - JR Z,Keuze2 8/13 2 - Keuze3: ..... - - Dit neemt 8 bytes in beslag (de jumproutine 11) en het neemt - 8 + 13 = 21 klokcycli als A=1 en 8 + 8 + 8 + 13 = 37 - klokcycli in beslag als A=2 en 8 + 8 + 8 + 8 = 32 klokcycli - als A=3. Zo heb je dus bij drie alternatieven minder bytes - en minder klokcycli nodig in vergelijking met de routine - Jump. (Indien JP nodig is in plaats van JR neemt het aantal - bytes met 2 toe waardoor het op 10 komt (nog steeds kleiner - dan 11) en het aantal klokcycli is respectievelijk 18 voor - A=1 en 36 voor A=2 en A=3. Nog steeds veel sneller dan de 68 - klokcycli van Jump.) We gaan er hier overigens wel vanuit - dat A alleen de waardes 1, 2 en 3 kan aannemen, want bij - deze routine zal ook bij A=0 en A=4 t/m A=255 de routine - Keuze3 worden uitgevoerd. - - - L U S S E N - - De Z80 heeft een simpele voorziening voor lussen in de vorm - van DJNZ (Decrease, Jump if NonZero). Hierbij is de - lusteller altijd B en is de maximale luslengte dus 256. Een - luslengte van 256 kan daarbij bereikt worden met 0 als - startwaarde van B!!! Een voorbeeld: - - klokcycli: bytes: - - LD B,10 8 2 - Lus: DJNZ Lus 14/9 2 - --- - 4 - - In totaal vergt deze lus 8 + 9*14 + 9 = 143 klokcycli. Deze - lus doet niets boeiend, alleen even wachten, 40.04 - microseconde om precies te zijn. Je kunt het ook zo - programmeren: - - klokcycli: bytes: - - LD D,10 8 2 - Lus: DEC D 5 1 - JR NZ,Lus 13/8 2 - --- - 5 - - Ik heb het expres met D gedaan om te laten zien dat je nu - niet meer aan B bent gebonden als lusvariabele. Het kost ��n - byte meer en verder vergt deze lus 8 + 10*5 + 9*13 + 8 = 183 - klokcycli (51.24 microseconde). Met DJNZ bespaar je dus - zowel ruimte als tijd, maar alleen B kan gebruikt worden als - lusvariabele. - - Grotere lussen kunnen gemaakt worden door geneste DJNZ- - lussen, bijvoorbeeld: - - LD B,100 - BuitensteLus: PUSH BC - LD B,100 - BinnensteLus: ...... - ...... - DJNZ BinnensteLus - POP BC - DJNZ BuitensteLus - - Hierbij wordt de binnenste lus 100 * 100 = 10000 maal - uitgevoerd. Dit is alleen geschikt voor vaste luslengte, en - dan vooral als er ook echt sprake is van een binnenste en - een buitenste lus. Bijvoorbeeld de binnenste lus doet iets - met alle dingen van ��n regel en de buitenste lus loopt alle - regels langs. Bij een variabele luslengte of als het - eigenlijk gewoon de bedoeling is dat de binnenste lus 10000 - maal wordt herhaald, is de volgende oplossing het meest - geschikt: - - LD BC,10000 - Lus: ...... - ...... - DEC BC - LD A,B - OR C - JR NZ,Lus - - Bij een 8 bits DEC (DEC A, B, C, etc.) wordt de Zeroflag - gezet als 0 wordt bereikt. Bij een 16 bits DEC is dit niet - het geval, DEC BC zet de Z-flag dus NIET als BC gelijk wordt - aan 0. Daarom kijken we met LD A,B; OR C of zowel B als C - gelijk zijn aan 0, want dan is automatisch BC gelijk aan 0. - - Dit doet me trouwens denken aan een verschil tussen DEC A en - SUB 1. Op het eerste gezicht doen deze twee instructies - exact hetzelfde, namelijk het verlagen van A met 1. Het - verschil zit hem echter in de vlaggen: bij DEC wordt de - carryflag niet be�nvloed, bij SUB 1 wel! Dus als A gelijk is - aan 0 en je doet DEC A, dan wordt er geen carry gezet, en - als A gelijk is aan 0 en je doet SUB 1, dan wordt de carry - wel gezet. Dit is echt zo'n irritant verschil waar je op - moet letten, want het kan soms hele vage bugs veroorzaken - omdat je ervan uitgaat dat de carryflag gezet wordt en het - gebeurt niet. [Ik had ergens SUB 1 in een source staan, en - toen zei iemand aan wie ik die source liet zien dat ik daar - DEC A van moest maken, omdat dat hetzelfde zou doen en - sneller is en minder bytes in beslag neemt. Ik had dat toen - veranderd en merkte pas later, toen diegene alweer weg was, - dat het programma niet meer werkte!] - - - 1 6 B I T S L D - - Veel 16 bits instructies die je vaak nodig hebt zoals LD - DE,HL; LD IX,HL en LD DE,IY bestaan niet. Hiervoor zullen we - dus andere oplossingen moeten zoeken. - - Ten eerste deze groep: - - LD BC,DE - LD BC,HL - LD DE,BC - LD DE,HL - LD HL,DE - LD HL,BC - - Deze instructies bestaan helaas niet maar ze zijn heel - makkelijk te maken met 8 bits LD instructies: - - LD BC,DE wordt: LD B,D - LD C,E - LD DE,HL wordt: LD D,H - LD E,L - etc. - - Zo'n "16 bits LD" kost 2 bytes en 10 klokcycli. Sommige - programmeurs gebruiken de volgende methode: - - LD BC,DE wordt: PUSH DE - POP BC - LD DE,HL wordt: PUSH HL - POP DE - - Dit kost ook 2 bytes maar is veel trager, want een PUSH kost - 12 klokcycli en een POP 11, waardoor het totaal op 23 komt. - Ofwel meer dan twee keer zo lang. - - Voor de tweede groep is dit (als je je aan de offici�le - instructieset van de Z80 houdt) niet mogelijk: - - LD IX,HL - LD IX,DE - LD IX,BC - LD IX,IY - LD HL,IX - LD DE,IX - LD BC,IX - LD IY,IX - - en dezelfde instructies met IY kun je alleen maken met een - PUSH en een POP. Bijvoorbeeld: - - klokc: bytes: - - LD IX,HL wordt: PUSH HL 12 1 - POP IX 15 2 - ---- --- - 27 3 - - LD BC,IY wordt: PUSH IY 16 2 - POP BC 11 1 - ---- --- - 27 3 - - Op de R800 [of met illegale instructies van de Z80 die je - dus niet mag gebruiken omdat ze bij de Z80's niet getest - zijn en dus fout kunnen gaan] kan het wel met 8 bits LD - instructies. Dit kan echter alleen met DE en BC, niet met - HL! Ook LD IX,IY en LD IY,IX kunnen alleen met PUSH en POP - worden opgelost. We schakelen nu bij het tellen van - klokcycli nu even over op klokcycli van de R800. Ik laat - voor LD IX,DE en LD BC,IY van beide alternatieven de - tellingen zien: - - LD IX,DE wordt: PUSH DE 4 1 - POP IX 4 2 - --- --- - 8 3 - - of: LD IXH,D 2 2 - LD IXL,E 2 2 - --- --- - 4 4 - - LD BC,IY wordt: PUSH IY 5 2 - POP BC 3 1 - --- --- - 8 3 - - of: LD B,IYH 2 2 - LD C,IYL 2 2 - --- --- - 4 4 - - Op de R800 is de variant met 8 bits LD dus twee keer zo snel - maar neemt wel een byte meer in beslag. Bovendien moet je - wel goed nadenken omdat niet alles mogelijk is. Maar als je - daar een fout mee maakt zal de compiler je wel waarschuwen. - Nog een nadeel hiervan is dat GEN80 en WB-ASS2 geen IXL, - IXH, IYL en IYH ondersteunen en je dus met DB's moet gaan - werken (DB #DD voor IX en DB #FD voor IY gevolgd door de - instructie op H of L). - - Dit was het voor deze keer. Veel succes met het programmeren - in ML, met vragen kun je natuurlijk altijd bij de redactie - terecht. - - Stefan Boer diff --git a/sunrise_special/7/Midi Cursus.md b/sunrise_special/7/Midi Cursus.md deleted file mode 100644 index 6018fae..0000000 --- a/sunrise_special/7/Midi Cursus.md +++ /dev/null @@ -1,563 +0,0 @@ - M I D I C U R S U S - - - C O N T R O L C H A N G E S - - Na de vorige keer een verhaal te hebben afgestoken over de - opbouw van MIDI-commando's wil ik het deze keer eens hebben - over de werkwoorden in de MIDI-taal: de CONTROL CHANGES. - - Zoals de vorige keer al opgemerkt (en ongetwijfeld nog - bekend...) begint een Control Change hexadecimaal met een B. - Daarachter komt, om het byte volledig te maken, een - hexadecimaal getal tussen 0 en F om het MIDI-kanaal aan te - wijzen, waarbij (zoals bekend) 0 kanaal 1 is en F kanaal 16. - Na dit statusbyte (want het begint met een getal groter of - gelijk aan 8) volgen twee databytes. Het eerste databyte - geeft de te veranderen controller aan, de tweede de waarde - die de controller krijgt. - - Ok�, tot dusver de herhaling; zijn er nog vragen? - - "Ja, wat is een controller?" - - Euh ja, goede vraag, maar niet zo goed te beantwoorden. Ik - kan simpelweg een cirkelredenering toepassen en zeggen dat - een controller datgene is, dat met behulp van Control Change - is te veranderen, maar dat is taalkundig niet erg netjes - (maar wel makkelijk, nietwaar heren politici?). - - Laat ik als antwoord op die vraag teruggrijpen op het - ontstaan van MIDI: - - Door de indeling van MIDI in status- en databytes - (respectievelijk die bytes groter dan of gelijk aan 128 en - kleiner dan 128) en de indeling van de statusbytes in vier - bits voor status en vier bits voor MIDI-kanaal bleef er voor - MIDI niet bijster veel meer over om te regelen. De vier bits - die de status aangeven (en dus ook nog MOETEN beginnen met - een 1, daar anders het getal kleiner is dan 128) kunnen - slechts 8 verschillende statussen aanduiden. Niet echt veel - om alle nuanceverschillen in muziek mee aan te sturen... - Daarom ontstond er de Control Change, als een soort - werkwoord voor de MIDI-taal: Alle parameters, die te - veranderen zijn met behulp van MIDI in een - keyboard/synthesizer en geen eigen Status hebben, worden - aangestuurd met de Control Change. In totaal zijn dus met - behulp van Control Change 128 verschillende parameters - (oftewel controllers) aan te sturen (databytes 00 t/m 7F). - Tot zover nog volledig duidelijk, hoop ik, en dus volgen nu - de uitzonderingen: - - De controllers (waarvan u dus nog steeds niet weet wat het - zijn; geduld, het wordt u wel duidelijk. Blijf rustig - doorlezen) zijn onderverdeeld in Continue controllers, - Switch controllers, geregistreerde en niet-geregistreerde - controllers. - - De Continue controllers zijn wederom onderverdeeld in - 14-bits controllers (dus twee databytes, later meer) en - 7-bits (oftewel 1 data-byte) controllers. - - De indeling in databytes is alsvolgt: - - 00h t/m 1Fh: 14-bits Continue controllers (MSB) - 20h t/m 3Fh: 14-bits Continue controllers (LSB) - 40h t/m 45h: Switch-controllers - 46h t/m 5Fh: 7-bits Continue controllers - 60h t/m 61h: data plus en data min (zie verder) - 62h t/m 65h: geregistreerde/niet-geregistreerde controllers - 66h tot 77h: nog niet gedefinieerd - 78h t/m 7Fh: Modusboodschappen (zie verder) - - - 14-BITS CONTINUE CONTROLLERS (MSB EN LSB) - - Als het eerste databyte na de statusbyte een getal is tussen - 00h en 3Fh, betreft het die controllers, die een waarde - kunnen bevatten tussen 0 en 16384. De databytes tussen 00h - en 1Fh geven de grove afstemming; die tussen 20h en 3Fh de - fijnafstemming. Controller 01h en 21h zijn dus DEZELFDE - controller, waarbij 01h de grove afstemming regelt en 21h de - fijnafstemming! V��r het ontstaan van de GM en GS-standaard - waren slechts 13 van de 32 14-bits Continue controllers - gedefinieerd: - - - 0 1 H / 2 1 H : M O D U L A T I O N - - Het doel van de modulation is om een geluid expressiever - weer te geven. Hoe dat gebeurt is aan de fabrikant om te - beslissen! De meest gebruikte modulations zijn de vibratie - (voor diegenen, die niet weten wat dat is: trilling...) en - de tremolo (variatie in de amplitude van een geluid). - - - 0 2 H / 2 2 H : B R E A T H C O N T R O L - - Omdat de DX7-synthesizer van Yamaha het eerste instrument - wat met een standaard in MIDI, zijn veel van zijn - controllers overgenomen. E�n van deze controllers was de - Breath Control. Voor diegene, die nog nooit iemand bezig - heeft gezien met de Breath Controller (en ik denk dat dat de - meesten zijn, daar deze controller eigenlijk alleen door - Yamaha ondersteund wordt en dan nog maar in beperkte mate. - Dadelijk wordt wel duidelijk waarom...): De Breath - Controller is een plastic mondstuk, waarin je blaast. - Naarmate je harder blaast, wordt de Breath Control hoger. - Het grote nadeel van deze controller is de mate van blazen - die nodig is om de maximale uitslag te krijgen: - Keyboard-spelers die rood aanlopen waren echt geen - zeldzaamheid, vooral niet als men roker was en/of net een - weinig (of wat meer) bier achterover had geslagen... - - - 0 4 H / 2 4 H : F O O T C O N T R O L L E R - - Speciaal voor rokers en drankorgels (en al de anderen, die - niet voor gek wilden staan met een buis in hun mond) - ontstond de Foot controller. Deze doet exact hetzelfde als - de Breath controller, maar wordt (hoera!) met de voet - bediend. - - - 0 5 H / 2 5 H : P O R T A M E N T O T I M E - - Deze controller regelt de snelheid van het portamento. - - "Euh, pardon? Wat is een portamento?" - - Jij weer? Nou vooruit: Portamento is een geleidelijke - overgang tussen twee noten. Denk bijvoorbeeld aan een - violist, die zijn vinger over een snaar laat glijden of aan - Brian May op overdrive-gitaar. Hoe hoger de waarde hoe - sneller naar de volgende noot wordt 'toegelopen'. - - (P.S. Er is ook nog een Portamento Switch-controller: Pas - als deze aan staat, werkt het portamento...) - - - 0 6 H / 2 6 H : D A T A E N T R Y - - Er zijn ook controllers, die geen ruimte meer hebben voor - databytes, doordat ze voor het aanduiden van de controller - al beide databytes nodig hebben. Een voorbeeld hiervan is de - verderop behandelde geregistreerde en ongeregistreerde - controllers. Om dergelijke controllers toch te kunnen - veranderen bestaat er de Data entry. De waarde die met deze - controller wordt gegeven wordt gebruikt om de LAATST gekozen - controller (geregistreerd of ongeregistreerd) te veranderen. - Heeft u nog geen controller gekozen gehad, heeft deze Data - entry ook geen effect... - - - 0 7 H / 2 7 H : M A I N V O L U M E - - Met behulp van deze controller wordt het volume van ��n - MIDI-kanaal veranderd. Deze controller is verreweg de meest - gebruikte, daar dit de enige standaard-methode is om het - volume van een keyboard/synthesizer te veranderen. - - - 0 8 H / 2 8 H : B A L A N C E - - Verwar deze controller niet met controller 10h/30h! De - balance regelt NIET de van audio-systemen bekende balance. - Daarvoor dient controller 10h/30h! De Balance regelt de - verhouding tussen twee geluiden, wanneer een voice is - samengesteld uit twee geluiden. Deze controller wordt - vrijwel alleen gebruikt bij synthesizers en dan nog niet - vaak! - - - 0 A H / 2 A H : P A N - - Deze controller be�nvloedt het stereobeeld van ��n - MIDI-kanaal. Wanneer de waarde 0 wordt meegestuurd bevindt - het geluid zich uiterst links. Naarmate de waarde hoger - wordt, verplaatst het geluid zich naar rechts, totdat de - maximale waarde is gegeven en het geluid zich dus uiterst - rechts bevindt. - - - 0 B H / 2 B H : E X P R E S S I O N - - Deze controller bepaalt het volumebeeld ter verfijning van - controller 07h/27h (Main volume). Voor die oplettende - mensen, die dus nu vragen of het volume dus in totaal - 28-bits geregeld wordt (controller 07h/27h=14-bits + - controller 0Bh/2Bh=14-bits) moet ik antwoorden: Officieel - wel, maar verreweg de meeste instrumenten (sterker nog: ik - ben nog nooit anders tegengekomen) herkennen alleen de MSB - van alle controllers. En om dan toch het volume wel met - behulp van 14-bits te regelen is de Expression ontstaan. - - - 10h/30h T/M 13h/33h: GENERAL PURPOSE - - Deze controllers zijn speciaal in het leven geroepen om de - diverse fabrikanten een mogelijkheid te geven om toch van - elkaar af te wijken. Deze controllers zijn dus NIET - standaard; elke fabrikant heeft ze met eigen controllers - ingevuld. Om weer terug te grijpen naar de vergelijking met - taal: Dit is het dialect van MIDI. - - - S W I T C H - C O N T R O L L E R S - - Dit zijn er in totaal 5. Deze controllers kennen slechts - twee standen: Aan en uit. Maar omdat MIDI alleen met 7-bits - databytes kan werken is 00h t/m 3Fh 'uit' en 40h t/m 7Fh - 'aan'. Persoonlijk vind ik dat ze deze switches best op - bit-niveau hadden kunnen zetten; dus 1 controller, die 7 - switches kan bedienen met het ene databyte van 7 bits! Maar - helaas kozen de MIDI-ontwerpers voor deze ruimte-vretende - oplossing. - - Zoals gezegd zijn de waarden 00h t/m 3Fh gelijk aan 'uit' en - 40h t/m 7Fh gelijk aan 'aan', maar dat heeft niet iedere - fabrikant begrepen. Verreweg het veiligst is het dus alleen - de waarden 00h (voor 'uit') en 7Fh (voor 'aan') te - gebruiken. - - De 5 switches in willekeurige volgorde zijn: - - - 4 0 H : D A M P E R P E D A L - - Dit is het sustain-pedaal van een piano. Wanneer deze - controller aan staat, wordt de toon niet meer uitgezet en - blijft dus eeuwig (in principe, tenminste) doorklinken. - - - 4 1 H : P O R T A M E N T O - - Inmiddels weet dus iedereen wat portamento is en kan ik hier - volstaan met de mededeling, dat deze controller dus het - portamento aan- en uitzet. - - - 4 2 H : S O S T E N U T O - - Sostenuto is in principe gelijk aan het Damper pedaal, met - dat verschil, dat het Damper-(oftewel sustain-)pedaal ook - die tonen, die later aangezet worden aanhoudt en het - sostenuto-pedaal alleen die tonen, die al aanstonden voordat - dit pedaal (controller) wordt aangezet, blijft aanhouden. - - - 4 3 H : S O F T P E D A L - - Aangezien een goede piano twee pedalen heeft (en een hele - goede zelfs drie, maar dat terzijde) regelt deze controller - het tweede pedaal, het soft-pedaal. Dit pedaal dempt het - geluid, zoals eenieder die ooit achter een piano gezeten - heeft (en natuurlijk ook gespeeld; alleen zitten levert bij - een piano weinig geluid op, uitzonderingen daargelaten) - weet. Voor die twee overblijvers: Ik kan hier wel een - uitgebreid verhaal gaan ophangen over de werking van dit - pedaal, maar verder dan de opmerking, dat het geluid minder - scherp klinkt, kom ik toch niet. Mocht u zich nog geen - indruk kunnen maken van dit effect, dan resteren er twee - mogelijkheden: 1) achter een piano gaan zitten en - uitproberen; of 2) (altijd de beste oplossing; ook voor alle - andere controllers) uitproberen via MIDI! - - - 4 5 H : H O L D 2 - - Deze controller dupliceert het sustain-pedaal wanneer er - tegelijk twee functies gebruikt moeten worden om een noot - aan te houden. Persoonlijk ben ik nog maar weinig - instrumenten tegengekomen, die deze controller herkennen. - - - De tekst wordt vervolgd in de volgende submenu-optie - - - - - - Dit is het vervolg van de tekst - - - M I D I C U R S U S - - - 7 - B I T S C O N T I N U E C O N T R O L L E R S - - Dit zijn de continue controllers, die niet via MSB en LSB - geregeld worden (hoewel ik al eerder opgemerkt heb, dat ik - persoonlijk nog geen instrument ben tegengekomen, dat de LSB - van die 14-bits continue controllers herkent...) maar - slechts 1 controller en dus 1 databyte genoeg vinden. Deze - zijn: - - - 50h T/M 53h: GENERAL PURPOSE CONTROLLERS 5 T/M 8 - - Naast de 14-bits controllers, die per fabrikant verschillen, - zijn er ook 4 7-bits controllers, die per fabrikant - verschillen. Elke fabrikant mag deze controllers naar eigen - goeddunken invullen; tussen verschillende instrumenten hoeft - dus geen herkenning op te treden, wanneer deze controllers - gebruikt worden. Misverstanden zijn echter wel te - verwachten: wanneer de ene fabrikant met controller 50h de - felheid van zijn display regelt (het is maar een - voorbeeld...) en een ander met controller 50h de leslie, - kunnen er nogal leuke effecten ontstaan, wanneer deze twee - instrumenten doorgekoppeld zijn! Denk in vergelijking maar - eens aan een rasechte Amsterdammer, die afzakt naar - Maastricht: Wat-ie al verstaat (dat zal wel niet veel zijn) - verstaat-ie waarschijnlijk nog verkeerd ook! - - - 5 B H T / M 5 F H : E F F E C T S - - Met deze 5 controllers worden 5 verschillende - effectprocessoren aangestuurd; deze zijn achtereenvolgens: - - - 5Bh: External effects depth (meestal een soort echo) - - 5Ch: Tremolo depth (om de mate van tremolo te regelen) - - 5Dh: Chorus depth (om de mate van chorus te regelen) - - 5Eh: Celeste (oftewel detune) depth - - 5Fh: Phaser depth (om het geluid 'uit fase' te zetten) - - Voor die enkeling, die nu het idee krijgt, dat ik weinig - informatie over dit onderwerp geef: Deze effecten zijn zo - apart, dat ze uitleggen eigenlijk afbreuk doet aan de - duidelijkheid; je moet ze horen om ze te begrijpen... En - bovendien zijn ze slechts sporadisch gebruikt, dus echt - belangrijk zijn ze niet (voordat ik de GS-kenners over me - heen krijg: Ja, op controllers 5Bh en 5Dh kom ik in het - GS-verhaal nog apart terug!). - - - 60h EN 61h: DATA INCREMENT EN DATA DECREMENT - - Via controller 06h/26h was het mogelijk data te versturen - naar aparte controllers. Welnu met de controllers 60h en 61h - is het mogelijk deze data respectievelijk met 1 te verhogen - of te verlagen. Net zoals bij controller 06h/26h al gezegd - hebben deze controllers voornamelijk invloed op de: - - - 62h T/M 65h: ON- EN GEREGISTREERDE CONTROLLERS - - Omdat de MIDI-ontwerpers een hekel hadden aan een eindig - aantal controllers, verzon men de geregistreerde (64h en - 65h) en de ongeregistreerde (62h en 63h) controllers. Het - verschil tussen deze twee is weer heel eenvoudig: De - geregistreerde zijn standaard, de ongeregistreerde zijn weer - per fabrikant anders. Verder zijn ze volstrekt hetzelfde - opgebouwd: - - De tweede databytes geven nu geen waarde aan maar een - volgende reeks controllers, waarbij de hoogste van elk paar - (bij de geregistreerde dus 65h, bij de ongeregistreerde dus - 63h) de MSB regelt en de laagste van elk paar (64h - respectievelijk 62h) de LSB. Het aantal controllers wordt in - ��n klap uitgebreid met 16384 nieuwe controllers! Bovendien - worden bij deze zgn. RPN (geregistreerde) en NRPN - (niet-geregistreerde) w�l zowel de MSB als de LSB verwacht! - - De waarde van de gekozen controller wordt achteraf veranderd - met behulp van de DATA-controllers (06h en 26h voor de - absolute invoer en 60h en 61h voor de relatieve invoer). - - Een voorbeeld, voor diegenen die naar duidelijkheid snakken: - - Om NRPN-controller MSB=00h/LSB=16h de waarde 54h te geven op - MIDI-kanaal 14, dient u alsvolgt de volgende bytes naar uw - instrument te sturen: - - BDh (B=Control Change; D=kanaal 14) - 63h (MSB van het NRPN eerst) - 00h (waarde van het MSB) - - BDh - 62h (LSB van het NRPN) - 16h (waarde van het LSB) - - BDh - 06h (DATA-invoer) - 54h (waarde van wijziging van NRPN 00h/16h) - - Zou de waarde nu een 14-bits getal geweest moeten zijn, dan - zou ook Controller 26h gebruikt hebben moeten worden en zou - het MIDI-event er alsvolgt uitgezien hebben: - - BDh 63h 00h BDh 62h 16h BDh 06h 04h BDh 26h 54h - - Voor diegenen die de 04h niet thuis kunnen brengen: Dit - slaat nergens op en is slechts bedoeld als voorbeeld. De - waarde die met dit laatste voorbeeld wordt uitgezonden, is: - - binair: &B00001001010100 - hexadecimaal: &H0454h - decimaal: 1108 - - Welke controller er nu veranderd is, kan ik natuurlijk niet - zeggen, daar dit (in tegenstelling tot de RPN-controllers) - bij de NRPN-controllers bij elk instrument anders is. Het - betreft hier ook maar een voorbeeld van het gebruik van de - NRPN- en RPN-controllers. - - De RPN-controllers zijn dus wel geregistreerd en voor die - grapjassen, die nu denken: "Ha, laat hem maar eens alle - 16384 controllers behandelen", kan ik antwoorden: Wie het - laatst lacht, lacht het best, want momenteel zijn er van de - 16384 geregistreerde controllers slechts 3 geregistreerd! - Deze zijn achtereenvolgens: - - MSB 00h/LSB 00h: PITCHBEND SENSITIVITY - - Met behulp van deze RPN-controller kan men aangeven hoeveel - noten een toon moet wijzigen bij een volledige uitslag van - het Pitch-bend-wiel. Het MSB van de data (06h) geeft het - aantal halve noten aan, het LSB het aantal honderdste van - een noot. - - MSB 00h/LSB 01h: FINE TUNING - - Hiermee kunt u uw instrument heel fijnschalig afstemmen: - Wanneer zowel MSB als LSB van de waarde 00h is, is uw - instrument 1 volledige halve noot verlaagd; is de MSB en LSB - daarentegen allebei 7Fh, dan is uw instrument een halve noot - verhoogd. Het gouden midden ligt bij MSB 40h en LSB 00h. Met - behulp van deze controller kunt u dus in 8192 stappen uw - instrument een halve toon verlagen en in 8191 stappen uw - instrument een halve toon verhogen! - - MSB 00h/LSB 02h: COARSE TUNING - - Gelijk aan FINE TUNING maar veel grofschaliger: Nu kunt u uw - instrument 64 halve noten verlagen en verhogen! Het midden - ligt uiteraard bij MSB=40h en LSB=00h. - - - M O D U S B O O D S C H A P P E N - - Poeh, poeh, we zijn er bijna: Als laatste onderdeel van de - Control changes worden nog even snel de 7 zgn. - modusboodschappen behandeld: Deze zijn achtereenvolgens: - - - R E S E T A L L C O N T R O L L E R S - - Wanneer de volgende MIDI-event wordt uitgezonden: - - Bxh 79h 00h - - Worden op het gewenste MIDI-kanaal (vul voor x een getal - tussen 0h en Fh in) in principe alle controllers van 00h t/m - 78h, de Pitchbend en de Aftertouch weer teruggezet op hun - beginwaarde. Ik zeg duidelijk in principe, want in de - praktijk worden over het algemeen maar een paar controllers - teruggezet. De fabrikant bepaalt namelijk zelf welke - controllers gereset worden en naar welke waarde ze gereset - worden... - - - L O C A L C O N T R O L - - Met de volgende MIDI-event: - - Bxh 7Ah 00h - - Wordt de local control afgezet. Wanneer als tweede databyte - in plaats van een 00h een 7Fh wordt uitgezonden, wordt deze - aangezet. Duidelijk toch... - - "Uhm, ben ik weer... Wat is Local Control eigenlijk?" - - Local Control regelt de verbinding tussen toetsenbord en - toongenerator. Wanneer Local Control aanstaat, wordt elke - toets, die op het toetsenbord wordt aangeslagen �n naar de - MIDI-out �n naar de toongenerator gestuurd, zodat er (als er - op de MIDI-out ook een instrument aangesloten is) twee - geluiden klinken. Staat nu de Local Control af, dan is de - verbinding tussen toetsenbord en toongenerator verbroken. - Elke toets, die nu aangeslagen wordt, wordt w�l naar de - MIDI-out gestuurd, maar wordt niet meer door het instrument - gespeeld. Daarentegen worden wel alle noten, die via MIDI-in - binnenkomen gewoon gespeeld. Het is alsof uw keyboard of - synthesizer is gesplitst in een apart commandotoetsenbord - (in Engels: Masterkeyboard) en een toongenerator. Wilt u in - dat geval toch geluid krijgen uit uw keyboard/synthesizer, - zult u de MIDI-out met de MIDI-in moeten verbinden! (PAS OP: - Staat Local Control aan, dan wordt dit geintje door diverse - fabrikanten ten strengste afgeraden!) - - - A L L N O T E S O F F - - Deze MIDI-boodschap (Bxh 7Bh 00h) zet alle tonen, die nog - aanstaan op het betreffende kanaal in ��n keer uit. Alleen - wanneer het sustain-pedaal aan staat (controller 40h) - behoren de tonen aan te blijven staan. In de praktijk blijkt - dit echter niet zo te zijn. Sommige fabrikanten houden zich - er netjes aan, anderen zetten ook dan alle noten uit. - - - O M N I O N / O F F ; P O L Y E N M O N O - - De volgende MIDI-events: - - Bxh 7Ch 00h (Omni mode off) - Bxh 7Dh 00h (Omni mode on) - Bxh 7Eh 00h (Mono mode on) - Bxh 7Fh 00h (Poly mode on) - - hebben invloed op de diverse MIDI-modi (enkelvoud: - MIDI-modus). Als enige overeenkomst zetten ze allemaal ook - alle noten uit. Voor de rest zijn deze MIDI-modi hopeloos - verouderd; vrijwel geen enkel hedendaags produkt maakt nog - gebruik hiervan. Dat wil geenszins zeggen, dat (zoals ik al - eens meegemaakt heb) deze MIDI-events als vervanging voor de - gewone ALL NOTES OFF gebruikt mogen worden! - - Voor de ge�nteresseerden: - MIDI kent 4 modi: - - 1) Omni on, poly - Het instrument accepteert alle voice-boodschappen over welk - kanaal dan ook en zal alle tonen aanzetten (tenzij het - instrument een polyfonie-grens heeft). - - 2) Omni on, mono - Het instrument accepteert alle voice-boodschappen over welk - kanaal dan ook, maar zal slechts ��n toon tegelijk laten - horen (speciaal voor oude, monofone synthesizers). - - 3) Omni off, poly - Het instrument accepteert alleen die voice-boodschappen, die - via hetzelfde kanaal komen als de OMNI OFF boodschap. Verder - zullen wel alle tonen, die via dat kanaal worden gestuurd - gespeeld worden (tenzij er een polyfonie-grens is). - - 4) Omni off, mono - Alleen die voice-boodschappen die via het, met behulp van - OMNI OFF, geselecteerde kanaal verstuurd worden, worden - gespeeld, maar nooit meer dan ��n tegelijk. Deze modus is - speciaal bedoeld voor MIDI-gitaar-spelers. Elke snaar op - zo'n gitaar correspondeert met een MIDI-kanaal. Op die - manier kan de gitaar-speler met behulp van zijn 6 snaren 6 - verschillende instrumenten aansturen. - - - S L O T - - Poeh, we zijn dan toch bij het einde van dit verhaal - gekomen. Zoals u wellicht is opgevallen, valt over de - Control Changes veel, heel veel te vertellen. Desondanks heb - ik alles slechts summier behandeld (enkele uitzonderingen - daargelaten). Voor diegenen, die willen gaan experimenteren - staat op deze diskette een BASIC-programma, dat via de Music - Module van Philips laat horen wat het effect is van elke - besproken controller. Gebeurt er op een gegeven moment - niets, dan ondersteunt uw instrument deze controller niet. - RUN't u het programma en er gebeurt helemaal niets, dan - dient u een Music Module, MIDI-kabels of een MIDI-instrument - te kopen en/of deze naar behoren met elkaar te verbinden - (MIDI-out naar MIDI-in). - - Ik wens u nog veel MIDI-plezier en tot een volgende keer... - - Ruud van Gestel diff --git a/sunrise_special/7/Music Module naar 256k.md b/sunrise_special/7/Music Module naar 256k.md deleted file mode 100644 index f2ea999..0000000 --- a/sunrise_special/7/Music Module naar 256k.md +++ /dev/null @@ -1,65 +0,0 @@ - M U S I C M O D U L E N A A R 2 5 6 K - - - Voor de mensen met twee rechterhanden wordt hieronder - beschreven hoe je je Music Module kunt uitbreiden naar 256 - kB samplegeheugen. Het zal nog veel even duren voordat de - nieuwe versie van MoonBlaster die dit ondersteunt er zal - zijn maar er is in ieder geval al de schitterende demo - Unknown Reality van NOP met schitterende lange samples. - - Uiteraard is Stichting Sunrise niet aansprakelijk voor - eventuele fouten die ontstaan naar aanleiding van het - uitvoeren van deze uitbreiding. - - Nodig: - - - Philips Music Module - - 2 geheugen-IC's type 44C256 - - Soldeerbout van ongeveer 30 Watt - - Soldeertin - - 20 cm dun draad - - Voor het gemak noemen we de 2 geheugen-IC's IC-A en IC-B. - - 1) Maak bij IC-A de volgende doorverbindingen: - - pen 1 aan pen 11 pen 2 aan pen 12 - pen 13 aan pen 18 pen 14 aan pen 19 - - 2) Maak bij IC-B de volgende doorverbindingen: - - pen 2 aan pen 7 pen 8 aan pen 18 - pen 9 aan pen 19 - - 3) Verbind nu de volgende pinnen van IC-A en IC-B: pen 3, 4, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20. - - 4) Zoek naar IC-8 in de Module en verbind de volgende - pennen van IC-B aan IC-8: - - IC-B IC-8 - pen 12 aan pen 10 - pen 3 aan pen 3 - pen 4 aan pen 4 - pen 6 aan pen 5 - pen 7 aan pen 7 - pen 8 aan pen 6 - pen 9 aan pen 12 - pen 10 aan pen 8 - pen 11 aan pen 11 - pen 13 aan pen 13 - pen 14 aan pen 9 - pen 15 aan pen 1 - pen 17 aan pen 15 - pen 20 aan pen 16 - - 5) Maak als laatste de volgende doorverbindingen op de Music - Module zelf: pen 16 van IC-A naar pen 8 van IC-2 en pen 9 - van IC-2 naar pen 36 van IC-10. - - 6) Maak de Module dicht en test deze bijvoorbeeld met - Unknown Reality van NOP. - - Bron: MAD Nieuwsbrief 6/94 - Met dank aan MSX Avengers Doetinchem diff --git a/sunrise_special/7/Nogmaals BDOS routines.md b/sunrise_special/7/Nogmaals BDOS routines.md deleted file mode 100644 index 3ba88c1..0000000 --- a/sunrise_special/7/Nogmaals BDOS routines.md +++ /dev/null @@ -1,497 +0,0 @@ - N O G M A A L S B D O S R O U T I N E S - - V O O R P R E T T I G E F I L E H A N D L I N G - - - Op Sunrise Special #4 staan twee artikelen met bijbehorende - listing van mijn hand over interfacing met de BDOS en disk - foutafhandeling onder DOS1. Geen commentaar was mijn deel. - Ik bedoel dat niemand die op dat moment even wat beter op de - hoogte was dan mijzelf zich goed genoeg voelde om mij mede - te delen dat er wat gevaren aan de routines kleven die ik in - de artikelen niet genoemd heb. Ik doel daarbij op het - wisselen van diskettes tijdens het lezen en schrijven van - komplete files. Lees ook het artikel op de vorige - submenu-optie. - - Ik heb de eerder gepubliceerde routines herschreven. Dat heb - ik gedaan om de error handler te debuggen en omdat ik tegen - de beperkingen van de routines aangelopen ben. Om het - geheugen even op te frissen: - - - Er kon maar ��n file tegelijkertijd open zijn - - De maximale handelbare filelengte was 64 kB - - Beide beperkingen zijn voor demo's en kleine utilities niet - erg vervelend, maar ik liep er tegen aan toen ik wat - ingewikkelde file-akties moest uitvoeren op meerdere files - tegelijkertijd. Het was dus tijd om het nog eens over te - doen waarbij beide beperkingen tot het verleden zouden - horen. - - Ik heb mij bij de ontwikkeling van de routines laten - inspireren door de ANSI-C standaard. De namen van de - routines kloppen niet met deze standaard, maar de - mogelijkheden komen redelijk overeen. - - Het doel van de routines is om 'dom' lees en schrijfwerk van - en naar diskettes, harddisks en wat je nog maar meer kunt - verzinnen wat eenvoudiger te maken. Op zich is het interface - van de BDOS naar de gebuiker goed (ook al is het al zo oud - dat Fred Flintstone het zich nog goed kan herinneren), maar - tijdens praktisch gebruik stoot je toch op wat zaken die - extra aandacht verdienen. - - Probeer je bv. een file van 1234 bytes in te lezen door een - random access block read van &H4000 bytes te doen dan gaat - dat wel goed, maar de call komt terug met de BDOS error code - A = 1. Wat moet je daar nu mee? Is er wat fout gegaan of is - dit juist een teken dat het goed ging? Als je er bij een - blockread voor zorgt dat er niet voorbij het End Of File - wordt gelezen, dan krijg je de foutmelding ook niet en is - het 'probleem' opgelost. Zo zijn er nog veel meer dingen die - door wat simpele testjes te doen, het leven van de - programmeur wat aangenamer kunnen maken. - - "Heeft die sukkel nu eindelijk DOS2 al eens ontdekt?", hoor - ik je zeggen. Welnu, ik ben een waanzinnig voorstander van - DOS2, maar ik vind het toch wat ver gaan om bij bv. spellen - en demo's (die niet uitsluitend voor de turbo R zijn) te - gaan eisen dat je DOS2 moet hebben. Daarom werken ook deze - routines nog gewoon met FCB's en zijn file-handles, - environment strings en sub-directories niet ge�mplementeerd. - Dat wil natuurlijk niet zeggen dat deze routines niet onder - DOS2 draaien. - - - D E F U N K T I E S - - Ik noem hier nu eerst even de funkties met hun aanroep etc. - waarna ik wat dieper op dit nieuwe ontwerp zal ingaan. - - ; BDOS fileshell routines for secure file loading and saving - ; File: BDOSR2.ASM V3.00 - ; By: Savage '94 (Fuzzy Logic) Last update: 29-07-94 - - ENASLT: EQU &H24 - PRINTC: EQU &HA2 - F##ERR: EQU &HF323 ; Double pointer to error routine - BDOS: EQU &HF37D - VDPBF1: EQU &HF3DF - VDPBF2: EQU &HFFE7-8 - - ; Jumpvectors - JP FINSTL - JP FRESET - JP FOPEN - JP FBLKRD - JP FCREAT - JP FBLKWR - JP FCLOSE - JP FSEEK - JP GETDIR - JP CHNDSK - JP DRVSTP - - ; Install BDOS fileshell - ; In : A (See BIOS rout 24H) - ; A must contain the settings for PAGE 1 (SLOT/SUBSLOT) - ; Out: Cy, on error - FINSTL: - - Deze routine moet worden aangeroepen voordat van de andere - routines gebruik gemaakt kan worden. In tegenstelling tot de - oude situatie wordt de BDOS entry nu niet meer afgebogen. - Het aanroepen van FINSTL: heeft verder geen gevolgen voor de - BDOS en andere routines zullen dus geen last van deze - installatie hebben. - - Bij invoer moeten in register A de slot en subslot - instellingen van PAGE 1 staan. Dit is nodig omdat de - DISK-ROM tijdens de error handler vrolijk op PAGE 1 aktief - staat en die moet door de error handler weer verwijderd - worden. - - - ; Reset BDOS fileshell - ; Out: Cy, on error - FRESET: - - Deze routine moet als laatste aangeroepen worden voordat met - iets anders begonnen wordt. In tegenstelling tot bij de oude - situatie is het gebruik van de BDOS door andere programma's - die niet van deze routines gebruik maken tussen een aanroep - naar FINSTL: en FRESET: niet langer aan beperkingen - gebonden. In de oude situatie werd een eventueel openstaande - file nog even gesloten. Nu wordt dat niet meer gedaan, maar - wordt alleen een waarschuwing gegeven dat er nog file(s) - open staan. - - - ;Set new 'disk error' handler and 'change disk' handler - INIERR: - - Deze routine wordt door de diskroutines aangeroepen voor ze - daadwerkelijk fysiek met de diskdrive aan de slag gaan. - Binnen deze funktie worden de BDOS error handler en de - 'change drive' hook van de BDOS afgebogen naar een eigen - routine. Nu hoor ik mensen al weer klagen dat dit een call - naar de BDOS alleen maar trager maakt en die mensen hebben - daarin wel gelijk. Deze vertraging is echter zo onmeetbaar - klein dat het de moeite van de overpeinzing niet waard is. - - - ;Reset disk handlers - EXIERR: - - Deze routine wordt na een fysieke aktie met de diskdrive - aangeroepen om de oude situatie van de BDOS error handler en - drive hook te herstellen. Zodoende zijn deze entries bv. - tussen een aanroep naar FOPEN: en FBLKRD: niet naar eigen - routines afgebogen. - - - ; Open a file - ; In : IX, Pointer to FCB - ; HL, Pointer to filenamestring (11 or 13 bytes long) - ; Out: Cy, on error - FOPEN: - - Bij aanroep van FOPEN: en FCREAT: hoeft van het 37 bytes - lange FCB bij invoer niets ingevuld te zijn. In assembly kan - dit FCB dus als volgt gedefinieerd worden. - - FCB: DS 37 - - In de filenamestring van 11 of 13 bytes staat de filenaam - van de file waar de aktie op uitgevoerd moet worden. In - assembly kan deze eenvoudig als volgt gedefinieerd worden. - - FLNAM1: DM "filename","ext" - FLNAM2: DM "A:filename","ext" - FLNAM2: DM "b:FiLeNaMe","ExT" - - In het eerste geval wordt de huidige drive (0) in het FCB - ingevult worden. In het tweede geval wordt specifiek drive - A: (1) in het FCB ingevuld en dat geldt ook voor B: (2). Een - ongeldige driveletter resulteert in een "File not found" of - "Cannot create" error bij resp. FOPEN: en FCREAT: Het maakt - niet uit of de string in kleine of hoofdletters wordt - ingevuld. - - - ; Read a block from the current fileposition - ; In : IX, Pointer to valid FCB - ; DE, Blocklength - ; HL, Loadaddress (not between 0x4000 and 0x7FFF) - ; Out: Cy, on physical load error - ; else, HL = the number of bytes actually read - FBLKRD: - - FBLKRD: zet zelf het DMA adres en controleert daarna of de - blokgrootte wel kan, door deze te vergelijken met de afstand - tussen de filelengte en het random record nummer. Indien het - blok niet past wordt de blokgrootte automatisch aangepast. - - - ; Create a file - ; In : IX, Pointer to FCB - ; HL, Pointer to filenamestring (11 or 13 bytes) - ; Out: Cy, on error - FCREAT: - - Zie ook FOPEN: - - - ; Write fileblock - ; In : IX, Pointer to valid FCB - ; DE, Blocklength - ; HL, Startaddress - ; Out: Cy, on error (File will be closed and deleted) - FBLKWR: - - De enige situatie waarin deze routine met een Cy terug komt - is als de gebruiker een (A)bort heeft gegeven, of als de - disk vol is. - - - ; Close file - ; In : IX, Pointer to FCB - ; Out: - - FCLOSE: - - Alleen files waarin geschreven is MOETEN met FCLOSE: - afgesloten te worden. - - - ; Fseek places the fileptr (random record number) on a - ; specified position - ; In : IX, Pointer to a valid FCB - ; HLDE, 32-bit offset value (HL = HIword) - ; A, 0 = Seek from the beginning of the file - ; 1 = Seek from the current position (curr_pos + - , offset) - ; 2 = Seek from EOF (EOF - offset) - ; Out: Cy, if the new offset is beyond EOF or A has an - ; invalid value - FSEEK: - - FSEEK: controleert of de opgegeven offset wel binnen de file - ligt en verandert (indien dit het geval is) het random - record number in het opgegeven FCB. De routine behandelt de - ingevoerde offset altijd als een positief getal. Negatieve - offsets leveren dus (meestal) een error op. - - - ; Read dir from disk - ; In : IX, Pointer to FCB - ; DE, Buffer for dir. (112*32+1 bytes) - ; HL, Directory search mask address - ; Out: Cy, HI then no files found - GETDIR: - - Vanaf register DE zal de directory van de disk in het - geheugen staan. Elke entry is 32 bytes lang en het einde kan - gevonden worden door te checken op een filenaam die met de - waarde 255 begint. - - - ; CHNDSK Set new drive - ; Request for same drive as current one is ignored !! - ; In: A, drive number (0=A: 1=B: etc.) - CHNDSK: - - Zie ook de verklarende tekst verderop. - - - ; Stop the diskdrive motor - DRVSTP: - - Zie ook de verklarende tekst verderop - - - ; BDOS error handler [system routine] - ; In: nothing - ; Out: nothing - DSERPT: DW ERRCDE ;Pointer to error code - ERRCDE: - - - ; Standard disk error handler - ; Request Abort or Retry input from the user - ABORET: - - ; 5 byte disk error hook - ; Out: A, "a" then abort disk action - ; "r" then retry last disk action - ; Remark: This hook can be used to include a customized - ; error handler - H.DERR: JP ABORET - DW 0 - - - ; Change disk query (hooked on &HF24F) - ; [BDOS system routine] - ; In : A, driveletter (in ASCII) - CHDSKQ: - - Deze routine moet het terugkeeradres van de aanroepende CALL - van de stack POPpen (de tweede POP AF in de listing) om te - voorkomen dat de BDOS ook nog eens een tekst print. - - - Deze tekst wordt vervolgd in de volgende submenu-optie - - - - - - Dit is het tweede gedeelte van de tekst - - - V E R V O L G B D O S - - - D E A A N P A S S I N G E N - - Een hele belangrijke aanpassing vind ik het feit dat het - BDOS entry point of &HF3DF niet langer direkt wordt - afgetapt. Hierdoor zullen andere routines die niet van het - bestaan van deze routines afweten er ook geen last van - hebben. Het lijkt mij dat deze aanpassing vooral de - betrouwbaarheid verhoogt. Daarnaast worden de BDOS error - handler en de 'change drive' hook per funktie ge�nstalleerd - en aan het eind weer verwijderd. Samengevat is het hele BDOS - systeem dus alleen afgetapt tijdens de executie van ��n van - deze routines. Dit is erg belangrijk als je tussendoor nog - andere programma's hebt die ook van de BDOS gebruik maken, - maar niet van deze routines. - - - L O S S E F C B S - - De andere belangrijke aanpassing is het feit dat nu een - eigen FCB aan de routines moet worden meegegeven. Dat lijkt - op het eerste gezicht een nadeel (meer invoerparameters), - maar het betekent wel dat er nu eenvoudig met meerdere files - tegelijkertijd gewerkt kan worden. - - - M A X F I L E L E N G T E 4 G B - - Het feit dat de max. filelengte waar nu mee gewerkt kan - worden 4GB is, lijkt op het eerste gezicht overbodig. Dat - verandert echter op het moment dat je n�t eventjes wat meer - dan 64kB wilt saven. De oude routines laten je dan hopeloos - in de steek. - - - R A N D O M F I L E A C C E S S - - Random file access is HEEL grappig. Wat sommige mensen niet - weten is dat random access op files niet alleen betekent dat - je zomaar overal binnen de bestaande file mag beginnen met - lezen of schrijven, maar dat er op een random access file - zowel lees als schrijfakties uitgevoerd mogen worden. Open - bv, een bestaande file met FOPEN: en niemand zal je - weerhouden om als eerste aktie met FBLKWR: een blok geheugen - in deze file te dumpen. Volkomen legaal, erg grappig en (op - PC's althans) een veel gebruikte methode om een harddisk als - virtueel geheugen te gebruiken. - - - D E R O U T I N E F S E E K : - - FSEEK: is een routine die in ANSI-C ongewijzigd hetzelfde - is. Het maakt het verplaatsen van het Random Record Number - (ook wel filepointer genoemd) even eenvoudig als het - wijzigen van het DMA adres. Het nut blijkt bij een nog door - mij uit te brengen cruncher waarbij ik nadat de komplete - file gecrunched en weggeschreven is, nog een header aan het - begin van de file moet invullen waar al wel ruimte voor - gereserveerd is. - - - D E R O U T I N E C H N D S K : - - De routine CHNDSK: in de oude routines is volledig - incompatible met de BDOS. Dat betekent dat een diskwissel - met deze routine niet aan de BDOS wordt doorgegeven en vice - versa. Nu is CHNDSK gewoon een aanroep van BDOS funktie 14 - en werkt het wel goed. - - Hierbij moet opgemerkt worden dat deze BDOS funktie niet - direkt bij aanroep om een nieuwe drivenummer vraagt. Dat - gebeurt pas bij de volgende aktie op die drive. Let hier een - beetje op i.v.m. spellen waar je niet te pas en te onpas - change disk meldingen wilt hebben. Je kunt het dan beter op - de oude manier doen waarbij het drivenummer in de FCB's - altijd 0 is. - - Vb: - - ; Stel de huidige drive is A: - LD A,(&HFCC1) ;BASIC ROM aktief - CALL FINSTL - - LD IX,FCB1 - LD HL,FLNAM1 - CALL FOPEN ;Open TEST.DAT op A: - JP C,FRESET ;Sukkel voor de computer !! - - LD A,1 ;Drive B: !!! (0 = A: etc.) - CALL CHNDSK - - LD IX,FCB2 - LD HL,FLNAM2 - CALL FCREAT ;Create TEST.CPY op B: - JP C,FRESET ;Nog meer sukkels - CALL FCLOSE - JP FRESET ;Wat een enorme file nietwaar? - - FCB1: DS 37 ;File op drive A: - FCB2: DS 37 ;File op drive B: - - FLNAM1: DM "a:test ","dat" - FLNAM2: DM "b:test ","cpy" - - De call naar CHNDSK: heeft niet tot gevolg dat de melding - "Insert disk for drive ..." in beeld komt. Dat gebeurt pas - binnen FCREAT:. Wordt dit 'programma' twee keer achter - elkaar opgestart dan wordt de tweede keer eerst om drive A: - gevraagd omdat tijdens het verlaten van het programma drive - B: nog ingesteld is. - - Deze manier van drivewisseling is echter erg leuk omdat - mensen met twee drives geen melding op hun scherm zullen - krijgen omdat er gewoon van twee drives gebruik gemaakt - wordt. Deze routine is eenvoudig uit te breiden tot een (te) - eenvoudig kopieerprogramma. Doordat de BDOS nu konstant op - de hoogte is van diskwisselingen, mag WEL van disk gewisseld - worden tijdens lees- en schrijfakties. De totale leesaktie - moet natuurlijk wel op dezelfde disk uitgevoerd worden en - dat laatste geldt natuurlijk ook voor de schrijfaktie. - - - D E R O U T I N E D R V S T P : - - DRVSTP: laat de drivemotor stoppen. Hier zijn in theorie - meerdere manieren voor. Ikzelf heb lange tijd de entry in de - BDOS zelf gebruikt omdat die onmiddellijk resultaat oplevert - en relatief snel is. Meneer Stefan Boer deelde me laatst - echter mede dat dit niet op alle MSX'en werkt (zucht, daar - gaan we weer). Het blijkt dat bepaalde knutselaars een - afwijkende DISK-ROM hebben waarbij die entry op een ander - adres terecht is gekomen. Ik ben nog nooit zo'n ding tegen - het lijf gelopen, maar gezien het feit dat veiligheid voor - alles gaat heb ik de routine dus maar weggeknikkerd. - - De vervanging die simpelweg 255 keer &HFD9F aanroept is de - oudste oplossing om de drivemotor te laten stoppen. De - andere methode waarbij eerst de 'motor delay counter' op 1 - wordt gezet waarna eenmalig &HFD9F wordt aangeroepen blijkt - volgens sommige bronnen ook niet altijd te werken en dus heb - ik ook die voorlopig overboord gezet. - - Er is mij nu wel op het hart gedrukt dat de nu - ge�mplementeerde routine de beste is omdat hij op ALLE MSX- - en werkt, maar ik heb um op mijn SONY eens aan het werk - gezet. Disassemblering van de routine op &HFD9F leert mij - dat er op een SONY helemaal geen drive stop wordt - aangeroepen en dat de drive volledig automatisch stopt (dat - was echter geen nieuws). Op een SONY is het 255 keer - aanroepen van &HFD9F dus niets meer dan een domme - vertraging. Kan iemand mij dan misschien vertellen wat er in - hemelsnaam op een Philips of turbo R gebeurt, want deze - drivestop lijkt me een beetje onzinnig. [Op een turbo R - stopt de drive ook automatisch, alleen op een (!#$%&) - Philips is het �berhaupt nodig om de drive stop te zetten.] - - - I N T E R R U P T S A A N E N U I T - - Tijdens een BDOS aanroep bij de oude routines wordt de - V_BLANK interrupt volledig uitgezet. Dat was innertijd om - mensen die nog steeds een trage DISK-ROM in hun SONY hebben - van enige snelheid te voorzien. Nu zit dit er niet meer in - om interruptproblemen bij bv. een aanroep naar BIOS funktie - &H9F te voorkomen. - - - T E N S L O T T E - - Ik heb deze routines al redelijk stevig getest en ik heb tot - op dit moment nog geen gekke onverklaarbare dingen - meegemaakt. Het aantal vernielde diskjes is ook 0, en dat - blijft hopelijk ook zo, zolang een komplete file - schrijfaktie maar op ��n en dezelfde disk wordt uitgevoerd. - Diskwisselingen die hier tussendoor komen mogen dus wel als - je gebruik maakt van de 'change drive' routine omdat de BDOS - er dan rekening mee houdt. - - Ik ben er persoonlijk wel happy mee. Beperkingen worden er - niet meer opgelegd en andere routines die wel van de BDOS - gebruik maken, maar niet van deze routines, hebben er - ab-so-luut geen last van. Het is zelfs zo dat er met bv. - FBLKRD: gelezen kan worden uit een file die niet met FOPEN: - geopend is. Dat alles in combinatie met een zeer eenvoudige - BDOS interfacing voor het lezen en schrijven van files maakt - deze routines voor mij in ieder geval onmisbaar. - - Alex van der Wal diff --git a/sunrise_special/7/Score in ML.md b/sunrise_special/7/Score in ML.md deleted file mode 100644 index e47e4f4..0000000 --- a/sunrise_special/7/Score in ML.md +++ /dev/null @@ -1,394 +0,0 @@ - S C O R E I N M L - - - Bij het maken van een spel loop je al snel tegen het - probleem op dat de grootste getallen die je in ML - fatsoenlijk kunt gebruiken (16 bits getallen) te klein zijn - om fatsoenlijk een score of iets dergelijks in op te slaan. - Bij Xak II is je maximale experience bijvoorbeeld 65535, en - dat staat gewoon niet professioneel. Voor leken is het - vreemd dat er zo'n vreemde bovengrens is (voor hen zou - bijvoorbeeld 99999 een veel logischere bovengrens zijn) en - degenen die een beetje ML kennen zien meteen dat ze bij - MicroCabin gewoon een 16 bits getal hebben gebruikt om de - experience bij te houden. - - Het afdrukken van een 16 bits getal is al redelijk - ingewikkeld (zie hiervoor de artikelen in MCCM, ik heb er - ook al eens aandacht aan besteed al was dat een minder - ingenieuze routine), maar als je grotere getallen wilt, 32 - bits bijvoorbeeld, dan wordt het helemaal een hele tour, - vooral om het ook nog een beetje snel te doen. En als je - bijvoorbeeld wilt dat de score snel kan oplopen, dan is zo'n - 32 bits afdrukroutine simpelweg te traag. Hoe goed je ook - kunt programmeren. - - - B C D - - Deze problemen heb je niet als je gebruik maakt van het BCD - formaat. BCD is een afkorting voor Binary Coded Decimal, een - codering waarmee je toch met decimale getallen kunt werken - op een computer die eigenlijk alleen geschikt is voor - binair, octaal en hexadecimaal. Dit is een 'native' datatype - van de Z80 processor, het wordt ondersteund door een aantal - vlaggen en instructies. Ik kom hier later nog op terug. - - Het BCD formaat werkt heel simpel, je zet gewoon in elke - nibble ��n cijfer van 0-9. De BCD notatie van het getal - 321456 is dus #32 #14 #56. De verzameling rekenroutines van - MSX-BASIC (bekend onder de naam MathPack) werkt ook met het - BCD formaat, waarbij het is uitgebreid met een exponent. - Voor scores e.d. is dat echter niet nodig en dus werken we - kale BCD, zonder exponent. - - - D A A - - Zoals ik al zei is BCD een native datatype van de Z80, en is - het dus relatief eenvoudig om routines voor het verwerken - van getallen in BCD formaat te schrijven. De Z80 instructie - die het meeste ingewikkelde werk uit handen neemt is DAA, - wat staat voor Decimal Adjust Accumulator. DAA zal - 'rekenfouten' die ontstaan bij optellen en aftrekken (en - alleen daarbij!) corrigeren zodat het resultaat ook weer in - BCD formaat staat. Ik zal dit verduidelijken met een - voorbeeld: - - LD A,#07 - ADD A,#07 - - A bevat nu de waarde 14, oftewel #0D. Het juiste antwoord - moet echter #14 zijn, want we werken met BCD formaat. Door - nu gewoon een instructie DAA te geven zal de Z80 deze - 'rekenfout' zelf corrigeren!!! Dus: - - LD A,#08 - ADD A,#05 - DAA - - A bevat nu de waarde #13! De Z80 heeft voor dit corrigeren - een aantal speciale vlaggen, waarvan je je misschien al - afvroeg waarom ze er zijn omdat je ze nooit gebruikt, er - zijn zelfs geen voorwaardelijke JP/JR/CALL/RET instructies - voor. Bit 1 van het F register is de N-vlag, die wordt gezet - als er een aftrekking plaatsvindt. De correctie is bij een - optelling namelijk anders dan bij een aftrekking. Bit 4 van - het F register is de H-vlag, de Half carry. Deze wordt gezet - als er een halfcarry optreedt van de low nibble naar de high - nibble van A. - - In bovenstaand voorbeeld is N niet gezet (er is opgeteld) en - H wel, er is immers een halfcarry opgetreden (5 + 8 is - groter dan 10). Hierdoor weet de Z80 dat hij 6 bij het - resultaat moet optellen. Dat klopt, want 13 + 6 = 19 = #13. - Nu een voorbeeld met aftrekken: - - LD A,#42 - SUB #07 - DAA - - Hier is weer een half carry, maar nu is er afgetrokken. #42 - - #07 = #3B. Aan de vlaggen kan de Z80 zien dat hij 6 moet - aftrekken om te corrigeren, en inderdaad #3B - #06 = #35 en - dat is precies het gewenste antwoord. Aan de half carry kan - de Z80 dus zien of er een correctie nodig is, en aan de - aftrekvlag kan hij zien of er 6 moet worden afgetrokken of - worden bijgeteld. Maar op zich hoef je dit niet eens te - weten om met DAA te kunnen omgaan. - - - S C O R E D A T A T Y P E - - We gaan nu een speciaal score datatype defini�ren. De - representatie, BCD zonder exponent, hebben we al, nu hebben - we nog een aantal operaties (lees: routines) met dit - datatype nodig. Hieronder volgen deze routines. Voor het - gemak gaan we ervan uit dat de lengte van de getallen altijd - even is, zodat er niet met halve bytes gewerkt hoeft te - worden. Bij alle routines wordt in B de lengte in bytes - meegegeven. - - - ; SCORE.GEN - ; Routines voor werken met getallen in BCD-formaat van - ; willekeurige lengte - ; Enige beperking is dat lengte altijd even moet zijn - ; Door Stefan Boer - - ; Waarschuwing: alle routines mogen AF, HL, BC, DE - ; veranderen!!! - - ; InitGetal - ; In : HL = ^getal, B = lengte/2 - ; Uit: getal is 0 - - Op zich een overbodige routine maar voor de volledigheid - staat hij erbij. Met ^ bedoel ik "pointer naar", dezelfde - notatie die bij Pascal gebruikt wordt. Deze routine maakt - dus het getal met lengte B waar HL naar wijst gelijk aan 0. - De implementatie is zeer eenvoudig: - - InitGetal: LD (HL),0 - INC HL - DJNZ InitGetal - RET - - - ; AssignGetal - ; In : HL = ^bron, DE = ^doel, B = lengte/2 - ; Uit: doel = bron - - Ook dit is weer een routine die er voor de volledigheid bij - zit. HL wijst naar het te kopi�ren getal, DE naar de - bestemming. De implementatie is weer triviaal: - - AssignGetal: LD C,B - LD B,0 - LDIR - RET - - - ; AddGetal - ; In : HL = ^getal1, DE = ^getal2, B = lengte/2 - ; Uit: getal1 = getal1 + getal2, carry als uitkomst te - ; groot en dan 999... - - Tel het getal waar DE naar wijst op bij het getal waar HL - naar wijst, en zet de uitkomst op de plaats waar HL naar - wijst. Dit is de eerste routine waarbij we DAA gaan - gebruiken. - - AddGetal: PUSH HL - PUSH BC - CALL MovePointers - - We bewaren HL en B even omdat we bij een te grote uitkomst - het hele getal met 9's moeten vullen. De routine - MovePointers verplaatst HL en DE naar het einde van het - getal. Dat is nodig omdat we van rechts naar links moeten - werken bij optellen, zoals je je misschien nog wel zult - herinneren van de lagere school. - - OR A ; wis carry - AddGetal_2: LD A,(DE) - ADC A,(HL) - DAA - LD (HL),A - DEC HL - DEC DE - DJNZ AddGetal_2 - - Dit is de feitelijke optelling. De cijfers worden per - groepje van twee (er zitten twee cijfers in ��n byte) bij - elkaar opgeteld, DAA zorgt dat ook het resultaat weer BCD - formaat is en we gebruiken ADC om de carry mee te nemen. - - POP BC - POP HL - RET NC - AddGetal_3: LD (HL),#99 ; overflow - INC HL - DJNZ AddGetal_3 - SCF - RET - - Als er geen carry is zijn we klaar, is er wel een carry dan - past de uitkomst niet, we vullen het getal met 9's en aan de - carry kan het programma zien dat er een overflow was. - - ; Zet DE en HL op einde van getallen - - MovePointers: PUSH BC - DEC B - JR Z,MovePointers_2 - MovePointers_1: INC DE - INC HL - DJNZ MovePointers_1 - MovePointers_2: POP BC - RET - - Als het getal 6 cijfers lang is (B=3), moeten we de pointer - 3-1=2 plaatsen opschuiven. Vandaar de DEC B. - - - ; SubGetal - ; In : HL = ^getal1, DE = ^getal2, B = lengte/2 - ; Uit: getal1 = getal1 - getal2, carry bij negatieve - ; uitkomst en dan 000... - - Aftrekken gaat net zo als optellen: - - SubGetal: PUSH HL - PUSH BC - EX DE,HL - CALL MovePointers - - Aangezien er geen SBC A,(DE) bestaat is het hier handiger - als DE en HL zijn verwisseld, vandaar de EX DE,HL. - - OR A ; wis carry - SubGetal_2: LD A,(DE) - SBC A,(HL) - DAA - LD (DE),A - DEC HL - DEC DE - DJNZ SubGetal_2 - - Ook hier hetzelfde als bij optellen, alleen wordt er nu - natuurlijk SBC gebruikt in plaats van ADC. - - POP BC - POP HL - RET NC - CALL InitGetal ; underflow - SCF - RET - - Voor het vullen met nullen hebben we al een routine dus die - gebruiken we ook. Omdat het vaak voorkomt dat je een getal - alleen maar met ��n hoeft te verhogen of verlagen heb ik - daar speciale routines voor. - - ; IncGetal - ; In : HL = ^getal, B = lengte/2 - ; Uit: getal = getal + 1, carry als getal te groot - - IncGetal: CALL MovePointers - IncGetal_1: LD A,(HL) - CP #99 - JR NZ,IncGetal_2 - XOR A - LD (HL),A - DEC HL - DJNZ IncGetal_1 - SCF - RET - IncGetal_2: ADD A,1 - DAA - LD (HL),A - OR A - RET - - Deze routine vervangt elke byte #99 vanaf rechts in #00 - totdat er een byte ongelijk is aan #99. Die wordt dan eentje - verhoogd (daarbij treedt nooit een carry op!), gecorrigeerd - met DAA en klaar is kees. Let op: in plaats van de ADD,1 mag - NIET door INC A worden vervangen! Want dan werkt DAA niet - meer goed. Decrease gaat net zo: - - ; DecGetal - ; In : HL = ^getal, B = lengte/2 - ; Uit: getal = getal - 1, carry als getal gelijk aan 0 - - DecGetal: CALL MovePointers - DecGetal_1: LD A,(HL) - AND A - JR NZ,DecGetal_2 - LD A,#99 - LD (HL),A - DEC HL - DJNZ DecGetal_1 - SCF - RET - DecGetal_2: SUB 1 - DAA - LD (HL),A - OR A - RET - - Getallen vergelijken is ook een belangrijke en vaak - voorkomende operatie: - - ; CompareGetal - ; In: HL = ^getal1, DE = ^getal2, B = lengte/2 - ; Z- en C-flag worden net als bij CP gezet - - De vlaggen worden dus hetzelfde gezet als bij CP. Dat is - niet alleen logisch maar ook nog eens het makkelijkst voor - de implementatie: - - CompareGetal: EX DE,HL - CompareGetal_1: LD A,(DE) - CP (HL) - RET NZ - INC HL - INC DE - DJNZ CompareGetal_1 - RET - - Ook hier weer een EX DE,HL omdat er nu eenmaal wel een CP - (HL) is en geen CP (DE). Zo gauw er een ongelijke byte - gevonden wordt zijn we klaar (RET NZ). Als de hele lus - doorlopen wordt zijn de getallen gelijk en is de Z-flag nog - gezet door de laatste CP. - - Tot slot nog de routine waar het allemaal omdraait: het - afdrukken! Deze routine is, zeker als je hem vergelijkt met - een routine voor het afdrukken van 16- of 32-bits getallen, - zeer snel. Bovendien zit je hier niet aan een maximale - lengte vast, nou ja, de maximale lengte is 512 cijfers! - - ; WriteGetal - ; In : HL = ^getal, B = lengte/2 - ; Getal wordt afgedrukt, routine PrintChar moet bekend zijn, - ; met als invoer A: ASCII van character, - ; mag HL, BC, DE wijzigen - - De manier van afdrukken ligt erg voor de hand, hierbij wordt - gewoon eerst het hoogste nibble genomen, naar het laagste - nibble geschoven, omgerekend naar ASCII en afgedrukt, en - daarna wordt het laagste nibble afgedrukt. - - WriteGetal: LD A,(HL) - EXX - PUSH AF - AND #F0 - RRCA - RRCA - RRCA - RRCA - ADD A,"0" - CALL PrintChar - POP AF - AND #0F - ADD A,"0" - CALL PrintChar - EXX - INC HL - DJNZ WriteGetal - RET - - Voor PrintChar kun je je eigen routine invullen om karakters - op het scherm te zetten. En hiermee is de verzameling - routines voor ons eigen BCD formaat compleet. - - - V O O R D E L E N E N N A D E L E N - - Tot slot nog even de voordelen en nadelen ten opzichte van - 16- of 32-bits getallen op een rij. - - Voordelen: - - - de lengte van de getallen is vrijwel onbeperkt (maximaal - 512 cijfers) - - de snelheid van het afdrukken is zeer snel - - Nadelen: - - - optellen en aftrekken gaat iets minder snel, hoewel het - meestal geen snelheidsproblemen zal opleveren - - vermenigvuldigen en delen is zeer moeilijk te programmeren - - Het snelheidsverlies bij optellen/aftrekken wordt zeker goed - gemaakt door het veel snellere afdrukken. Vermenigvuldigen - en delen gaat met 16- en 32-bits getallen ook al niet - makkelijk, maar hierbij is het helemaal ingewikkeld. Maar - vermenigvuldigen en delen heb je weinig nodig in spellen, en - als het toch nodig is kun je het altijd met herhaald - optellen/aftrekken programmeren. Niet echt snel maar het - werkt wel. - - Stefan Boer diff --git a/sunrise_special/7/Toetsenborden en microbiologie.md b/sunrise_special/7/Toetsenborden en microbiologie.md deleted file mode 100644 index 9c61e49..0000000 --- a/sunrise_special/7/Toetsenborden en microbiologie.md +++ /dev/null @@ -1,113 +0,0 @@ - T O E T S E N B O R D E N E N - - M I C R O B I O L O G I E - - - Ik durf te beweren dat de Sony HB-F___ serie MSX2 computers - de beste toetsenborden voor MSX computers hebben. Die weke - Philips en Panasonic troep kan mij niet in vuur en vlam - zetten, noch kan ik mij lovend over beide inferieure - ramplanken uitspreken (alhoewel er toch wel aan te wennen - is). - - U merkt het al, deze jongen heeft (nog) een Sony; een erg - oude Sony overigens. Wij praten hier over het tijdperk van - voor Methusalem toen ik met mijn in de jeugdjaren bijelkaar - geslijmde kwartjes en stuivers (mijn grootouders waren - altijd al wat ouderwets zonder besef van inflatie) tot - trotse bezitter maakte van wat toen de cr�me de la cr�me van - MSX technologie was. - - Zelden heeft een toestenbord zo moeten lijden als onder mijn - regime. Heus, als er een Amnesty International voor - toetsenborden zou bestaan dan zou ik bovenaan de jaarlijkse - zwarte lijst staan als uiterst gemene tiran die zijn toetsen - jaar in jaar uit meedogenloos weet te onderdrukken - (doordrukken zou een beter woord zijn). - - Maar helaas, zelfs Japanners kunnen niet iets maken dat - blijvend is. Mijn toetsenbord begon het te begeven, na jaren - van trouwe dienst. Het begon met een haperende BACKSPACE - toets (erg lastig overigens) en eindigde in een dramatische - huilbui toen ik op een gegeven moment alleen nog met een - hamer de BACKSPACE kon bewegen van positie te veranderen. - - Tijd voor een schoonmaakbeurt. Met goed fatsoen de onderkant - verwijderd om daarna met de mond vol tanden te staan. Nog - nooit had ik zoveel (geborgde) schroefjes op 1 print - bijelkaar gezien. Vol goede moed toch maar de - schoevendraaier gepakt en aan het werk gegaan. Dat bleek - niet mee te vallen, mijn fysiotherapeut beschuldigde me er - later van dat ik een notoir bierdrinker moest zijn om op - zo'n leeftijd al zulke versleten polsen te kunnen hebben. - - Affijn, de print liet uiteindelijk los en toen maakte ik de - kapitale fout door het hele zootje eens om te draaien. Mijn - mooie zwarte bureaublad lag plotseling bezaaid met stukjes - Alex. Duidelijk waren perioden van roos en nagelbijten in - mijn prille pubertijd zichtbaar als sedimentlagen in een - rivierbedding. Enkele reeds uitgestorven insektensoorten - bleken in gemummificeerde vorm tevoorschijn te komen en de - heren biologen zijn nog steeds bezig om alle nieuw ontdekte - mossen, schimmels en zwammen te klassificeren. Ik snap nu - wat men bedoeld met de uitspraak dat de computerbusiness - 'leeft'. - - Het is op zijn minst grappig dat de natuur zo'n grote - invloed op de computer industrie heeft. Wist u bijvoorbeeld - dat de term 'debuggen' stamt uit de jaren 50 toen men een - overklaarbare fout constateerde in een van de toen gangbare - buizen computers. Na heel veel speurwerk vond men het - probleem. Het bleek te gaan om een kevertje ('bug' in het - Engels) dat kortsluiting in de bedrading had veroorzaakt. - Laat u dus geen oor aannaaien als iemand meedeeld dat een - 'debugger' een programma is. In werkelijkheid is het een - hoog opgeleide ingenieur die zich in onmogelijke bochten - wringt op zoek naar gebraden torretjes in kamergrote - computers. - - Toen deze macabere wereld al zijn geheimen aan mijn - bureaublad had blootgegeven heb ik het maar eens kennis - laten maken met een afvalbak. Ik had al eens gehoord dat er - soms de meest wilde dingen in toetsenborden worden gevonden, - maar dat het zo erg is; nee dat had ik niet gedacht. Ik kan - niet zeggen dat ik het vreemd vond dat de BACKSPACE toets - het niet meer deed. - - Overijverig dat ik was maakte ik de tweede kapitale blunder; - ik haalde de kontaktspray tevoorschijn. De print was nl. - voorzien van een aangebrachte zwarte substantie (ik vermoed - een koolstofmix) op de kontaktpunten voor de toetsen. De - toetsen blijken een soort membramen die door het indrukken - van een toets naar buiten worden geforceerd. Aan het - uiteinde van zo'n membraam hangt een klein zwart rondje dat - het feitelijke kontakt tussen de kontaktpunten op de print - maakt. Deze zwarte rondjes zijn van een nog niet nader - ge�dentificeerde materie. Ik vond die van de BACKSPACE toets - wat smerig en bedolf hem derhalve uit pure frustratie in - kontaktspray. - - Dat had ik beter niet kunnen doen. Enig doorfluiten - (elektrotechnische term voor het meten van weerstand) leerde - me nl. dat de zwarte rondjes niet geleidend waren, maar dat - er een substantie op zit die dat wel is. Deze substantie had - ik bij de BACKSPACE toets dus weggespoten met het - oplosmiddel in de kontaktspray. Om deze fout te herstellen - heb ik een CODE toets opgeofferd (waar je toch 2 van hebt) - om deze met de BACKSPACE toets te vervangen. - - Later had ik echter een ideetje. Ik schroefde de ramplank - weer open (daar gaan je polsen) en heb toen een uiterst - miniem klein stukje zilverfolie op het zwarte rondje van de - niet langer werkende CODE toets geplakt. Dat bleek genoeg om - de toets weer beter te maken dan hij ooit geweest is. Let - natuurlijk wel op dat de lijm alleen aan de goede kant van - de zilverfolie komt, want er zijn bij mijn weten niet zoveel - elektrisch geleidende lijmen. - - Kortom, de toetsenborden van SONY's zijn uitstekend te - repareren. Ik wens potenti�le reperateurs veel succes bij - hun speurtocht door de sedimentlagen van hun lichamelijke - geschiedenis. - - Alex van der Wal diff --git a/sunrise_special/7/VDP Cursus 11.md b/sunrise_special/7/VDP Cursus 11.md deleted file mode 100644 index 5e6f653..0000000 --- a/sunrise_special/7/VDP Cursus 11.md +++ /dev/null @@ -1,334 +0,0 @@ - M S X 2 / 2 + V D P C U R S U S ( 1 1 ) - - - P A L E T S P L I T - - We gaan deze keer een voorbeeld van een zogenaamde - paletsplit behandelen. Dit is een screensplit, waarbij het - palet wordt veranderd bij de screensplit. Hierdoor kunnen er - dan bijvoorbeeld 32 kleuren tegelijk op het scherm in SCREEN - 5. Eerst maar even wat theorie. - - - P A L E T A A N S T U R E N - - De VDP heeft 16 paletregisters, die worden aangeduid met P#0 - t/m P#15. Deze paletregisters kunnen niet direct worden - beschreven, en het is helemaal niet mogelijk om palet- - registers uit te lezen. - - De paletregisters kunnen alleen indirect worden beschreven, - en wel door eerst het palet te selecteren door het nummer - naar R#16 te schrijven en vervolgens de paletdata naar Port - #2 te sturen (I/O poort &H9A). - - De paletdata bestaat uit twee bytes, waarvan slechts 9 bits - van belang zijn. Drie bits voor rood, drie bits voor blauw - en drie bits voor groen. De twee bytes met paletdata zijn - als volgt opgebouwd: - - MSB 7 6 5 4 3 2 1 0 LSB - 0 ----R---- 0 ----B---- 1e byte - 0 0 0 0 0 ----G---- 2e byte - - Let op, want de volgorde is niet R,G,B zoals bij de COLOR= - instructie in BASIC maar R,B,G. De handigste notatie om - paletbytes weer te geven is door de eerste byte in hex te - zetten en de tweede gewoon in decimaal, dus zo: - - &HRB,G - - Waarbij R, B en G zoals we gewend zijn lopen van 0-7. De - kleur met R=3, B=7 en G=1 wordt dus: - - &H37,1 - - Tot slot geef ik nog even een voorbeeld van de complete - procedure die moet worden gevolgd om de BASIC instructie - COLOR=(13,7,2,5) in ML te maken: - - DI - LD A,13 - OUT (&H99),A - LD A,16+128 - OUT (&H99),A ; selecteer P#13 - EI - LD A,&H75 ; R=7, B=5 - OUT (&H9A),A - LD A,2 ; G=2 - OUT (&H9A),A - - De DI en EI instructies zijn nodig omdat de interrupts - altijd uit moeten staan als we naar een VDP register - schrijven. Bij het schrijven van de paletregisters is dit - alleen nodig als er op de interrupt ook iets met de - paletregisters zou kunnen worden gedaan. In dat geval moet - de EI verhuizen naar het einde van de routine. - - Tot slot moeten we nog weten dat de paletpointer (R#16) - automatisch wordt verhoogd na het ontvangen van twee palet - bytes van Port #2 en daarbij na P#15 weer verder gaat bij - P#0. Als we bij bovenstaand voorbeeld dus ook nog kleur 14 - zouden willen veranderen, kunnen we volstaan met het - schrijven van de twee paletbytes naar &H9A. - - - S C R E E N S P L I T - - De theorie over het palet is nu in voldoende mate behandeld, - maar voor een paletsplit hebben we ook een screensplit - nodig. Ik prefereer de zogenaamde "polling screensplit". Dit - zegt u waarschijnlijk weinig, tenzij u de tekst over - Interrupt Service Routines op Sunrise Special #2 hebt - gelezen. Daar wordt namelijk uitgelegd wat polling is. - - Er zijn twee manieren om een screensplit te detecteren. De - eerste manier is door de VDP de opdracht te geven een - interrupt te genereren zodra hij bij een bepaalde beeldlijn - is bij de schermopbouw. De computer springt bij de interrupt - naar adres &H38 en komt zo vanzelf bij de hook &HFD9A - terecht. Als je die hook afbuigt met je eigen routine kun je - de screensplit verder afhandelen. - - Er is echter een veel simpeler manier, die bovendien sneller - reageert op de screensplit, en dat is polling. Bij polling - wacht je gewoon totdat de VDP bij de juiste lijn is - aangeland met de schermopbouw. Als je dit een beetje slim - uitkient neemt het ook nog eens minder processortijd in - beslag dan de interruptmethode. Bij de interruptmethode - worden namelijk alle registers op de stack gePUSHt, en wordt - er flink wat heen en weer gesprongen voordat de computer - eindelijk bij jouw screensplitroutine is. Bij polling is dat - allemaal niet nodig. - - - S C R E E N S P L I T M E T P O L L I N G - - Hoe werkt nu zo'n screensplit met polling. Vrij eenvoudig. - Je moet het programma zo programmeren dat je per interrupt - werkt. Aan het begin zet je een HALT neer. Een HALT wacht op - een interrupt. Dit is normaal gesproken altijd de 50 of 60 - Hz interrupt, die optreedt als de VDP met de schermopbouw - bij lijn 212 is aangeland. HALT laat die interrupt eerst - uitvoeren, en daarna wordt er verder gegaan met het - hoofdprogramma. - - Heb je bijvoorbeeld de replayroutine van MoonBlaster aan - &HFD9F hangen, dan wordt de muziek dus eerst afgespeeld. Na - de HALT doe je de scherminstellingen voor het bovenste - gedeelte van het scherm. In dit geval is dat dus het naar de - VDP sturen van het palet voor het bovenste gedeelte. - - Vervolgens ga je andere dingen doen (bijvoorbeeld het - toetsenbord uitlezen, berekeningen doen, etc.), en je mikt - het ongeveer zo uit dat de computer daarmee klaar is als de - VDP met de beeldopbouw bij de screensplit is aangeland. - - Nu zet je de lijn voor de screensplit in R#19. De VDP zal nu - bit 0 van S#1 zetten zodra hij bij die lijn is. Je checkt - dus bit 0 van S#1 net zolang totdat het op 1 springt. Dan - stuur je het palet voor de onderste helft van het scherm - naar de VDP. Vervolgens heb je nog tijd om andere dingen te - doen. Als je er maar voor zorgt dat de computer weer op tijd - bij de HALT is. - - - M E E R D E R E S C R E E N S P L I T S - - Het grote voordeel van deze methode is dat meerdere - screensplits geen enkel probleem zijn. Gewoon nog een keer - het screensplitroutinetje erin zetten, alleen dan met een - andere lijn. - - Bij de interruptmethode wordt dit toch ingewikkelder, omdat - de computer bij elke interrupt (ook de 50/60 Hz interrupt!) - naar &HFD9A springt, zodat je in die routine eerst moet - uitzoeken welke screensplit het eigenlijk is. - - Genoeg theorie, we gaan gauw verder met het voorbeeld. Hier - komt de assemblerlisting, zoals gewoonlijk rijkelijk - voorzien van uitleg. - - - ; PALSPLIT.ASM - ; Voorbeeld paletsplit: 32 kleuren op het scherm - ; VDP Cursus Sunrise Magazine #6 - ; Stefan Boer 18/01/93 - ; (c) Ectry 1993 - - LINE: EQU 106 - - ORG &HD000 - DI - XOR A - OUT (&H99),A - LD A,16+128 - OUT (&H99),A ; P#0 selecteren - - - Hier wordt P#0 geselecteerd. Dit hoeven we slechts ��n keer - te doen, omdat we toch elke keer alle 16 paletregisters - beschrijven. Na afloop staat de paletpointer dan immers toch - weer op 0. Hierna begint de hoofdlus: - - - UPPER: EI - XOR A - CALL &HD8 ; spatiebalk testen - RET NZ - - - Door de routine GTTRIG op adres &HD8 aan te roepen met de - waarde 0 in het A register vragen we de status van de - spatiebalk op. Als de spatiebalk is ingedrukt wordt de - routine be�indigd. - - - HALT ; wacht op interrupt - - - Hier wordt op de interrupt gewacht, dit is dus de - 'screensplit' op lijn 212. - - - DI - LD HL,PALET1 ; palet voor bovenste helft - LD BC,&H209A ; 32 bytes naar poort &H9A - OTIR ; stuur palet naar VDP - - - De interrupts worden uitgezet, al is dat eigenlijk niet - nodig omdat er in de praktijk toch geen interrupts optreden. - Vervolgens wordt het palet met een OTIR instructie naar de - VDP gestuurd. Omdat we in dit voorbeeld verder toch niets te - doen hebben gaan we gelijk verder met de screensplitroutine. - - - LD A,LINE - OUT (&H99),A - LD A,19+128 - OUT (&H99),A ; lijn voor screensplit - - - Hier wordt de lijn voor de screensplit naar R#19 geschreven. - LINE is aan het begin van de listing met een EQU op 106 - gezet, dat is het midden van het scherm (want dat is 212 - lijnen). - - - LD A,1 - OUT (&H99),A - LD A,15+128 - OUT (&H99),A ; S#1 selecteren - NOP - NOP ; geef VDP tijd om data klaar - ; te zetten - LOWER: IN A,(&H99) ; lees S#1 - BIT 0,A ; test op screensplit - JP Z,LOWER ; lijn nog niet bereikt - - - We selecteren eerst S#1, zodat we die kunnen lezen door Port - #1 (poort &H99) te lezen. De twee NOPjes zijn nodig om de - VDP de kans te geven de juiste data op &H99 te zetten. - Vervolgens wachten we tot bit 0 van S#1 op 1 springt. Dan - weten we dat de VDP bij lijn 106 is aangeland. - - - LD HL,PALET2 ; palet voor onderste helft - LD BC,&H209A ; 32 bytes naar poort &H9A - OTIR ; stuur palet naar VDP - - - We sturen op de inmiddels bekende wijze het palet naar de - VDP. - - - XOR A - OUT (&H99),A - LD A,15+128 - OUT (&H99),A ; weer S#0 voor BIOS - - - Dit is belangrijk, voor de BIOS moet S#0 altijd zijn - geselecteerd. Om het BIOS zo snel mogelijk te houden wordt - er namelijk simpelweg IN A,(&H99) gebruikt om S#0 te lezen. - - - JP UPPER - - - En tot slot springen we weer naar de bovenste screensplit, - waar eerst nog even op de spatie wordt gecheckt. Nu nog de - paletten invullen: - - - ; palet voor bovenste helft van scherm - - PALET1: DB &H00,0,&H11,1,&H22,2,&H33,3 - DB &H44,4,&H55,5,&H66,6,&H77,7 - DB &H10,0,&H20,0,&H30,0,&H40,0 - DB &H50,0,&H60,0,&H70,0,&H77,0 - - ; palet voor onderste helft van scherm - - PALET2: DB &H00,0,&H01,0,&H02,0,&H03,0 - DB &H04,0,&H05,0,&H06,0,&H07,0 - DB &H00,1,&H00,2,&H00,3,&H00,4 - DB &H00,5,&H00,6,&H00,7,&H07,7 - - - De hier gegeven data is natuurlijk volslagen willekeurig, u - kunt hier zelf invullen wat u wilt. Deze assmblerlisting - staat als PALSPLIT.ASC op de diskette, geassembleerd onder - de naam PALSPLIT.BIN. - - - V O O R B E E L D - - In PALSPLIT.PMA zit het voorbeeldprogramma PALSPLIT.BAS, dit - programma tekent 2 maal 15 verticale balken in SCREEN 5 om - de routine uit te testen. Er zijn dan dus 31 kleuren - tegelijk op het scherm (30 balken + achtergrondkleur = - zwart). - - - N E T T E P A L E T S P L I T - - U zult bij het voorbeeld helemaal niets merken van de - paletsplit. Dit komt omdat de split ergens bij lijn 106 zit, - en daar zit alleen kleur 0. Ik heb kleur 0 express in beide - paletten hetzelfde gehouden, zodat de overgang niet te zien - is. - - Kijk maar eens wat er gebeurt als u kleur 0 wel verschillend - maakt, dan kun je duidelijk de screensplit zien zitten. Je - ziet ook dat hij trilt. - - Bij andere screensplits kun je de split wegwerken door op - een bit van een statusregister te checken dat aangeeft dat - de VDP begint met het opbouwen van de lijn. Omdat dat niet - precies klopt moet er dan ook nog een wachtlusje bij. - Waarschijnlijk kom ik daar in een later deel van de VDP - cursus nog wel eens op terug. - - Bij een paletsplit is de hier gebruikte oplossing echter - beter, het kost vrijwel geen moeite en je ziet de split - absoluut niet. Zorg dus dat kleuren die in het overloop- - gebied voorkomen in beide paletten hetzelfde zijn, dan zie - je niets van de paletsplit. - - - 5 1 2 K L E U R E N - - Ik denk dat het mogelijk is om met behulp van deze routine - alle 512 kleuren tegelijkertijd op het scherm te krijgen in - SCREEN 5, door gewoon het screensplitstuk een flink aantal - keren achter elkaar te zetten en voldoende verschillende - paletten toe te voegen. Ik heb het zelf nog niet geprobeerd, - misschien een andere keer. - - Veel succes met het experimenteren met deze routine en tot - de volgende keer. - - Stefan Boer diff --git a/sunrise_special/7/VDP Cursus 12.md b/sunrise_special/7/VDP Cursus 12.md deleted file mode 100644 index 0230be1..0000000 --- a/sunrise_special/7/VDP Cursus 12.md +++ /dev/null @@ -1,314 +0,0 @@ - M S X 2 / 2 + V D P C U R S U S ( 1 2 ) - - - Welkom bij het twaalfde deel van de inmiddels legendarische - VDP cursus. Ook deze keer gaan we weer een ML routine - bespreken. Dit keer is het een routine om tekst met een - grafische karakterset op het scherm te zetten in SCREEN 5. - De theorie die hiervoor nodig is is allemaal al aan bod - geweest, dus we beginnen meteen met de source. - - In dit voorbeeld gebruiken we een 6x8 karakterset, maar het - is heel eenvoudig om de routine aan te passen zodat - karakters van andere formaten worden gebruikt. Ik geef de - routine hier in de BASIC uitvoering, maar hij kan natuurlijk - ook gewoon in een puur ML programma worden gebruikt. - - - ; P R T E X T . A S M - ; Zet tekst op scherm in SCREEN 5 met COPY (font in page 3) - ; Aanroepen door coordinaten in te POKEn: - ; POKE &HD003,X : POKE &HD004,Y - ; en daarna U$=USR("tekst") - ; Door Stefan Boer, (c) Ectry 1993 - ; VDP Cursus Sunrise Magazine #7 - - ORG &HD000 - - JP PRTEXT - XCOOR: DB 0 - YCOOR: DB 0 - - - Dit ziet er misschien een beetje vreemd uit, maar dit is - gedaan om het aanroepadres en de adressen van de co�rdinaten - die moeten worden ingePOKEt standaard te houden. - - - PRTEXT: LD A,(DE) - LD B,A - INC DE - LD A,(DE) - LD L,A - INC DE - LD A,(DE) - LD D,A - LD E,L ; DE=startadres, B=lengte - - - Als je een ML routine vanuit BASIC aanroept met - - U$= USR(string) - - dan staat in het DE register het begin van de zogenaamde - "string desriptor". Deze string descriptor bestaat uit drie - bytes. De eerste is de lengte van de twee strings, de twee - andere bytes geven het beginadres in het geheugen staan. - Hier zetten wij het beginadres in DE en de lengte in B. - - - LD A,(XCOOR) - LD (COPDAT+4),A ; DX invullen - LD A,(YCOOR) - LD (COPDAT+6),A ; DY invullen - - - Hier worden de ingePOKEte co�rdinaten in de copydata - ingevuld. - - - PRINT: PUSH BC ; bewaar aantal karakters - LD A,(DE) ; haal teken - INC DE ; DE wijst naar volgende teken - SUB 32 ; eerste karakter is spatie - ADD A,A ; A=A*2 - LD C,A - LD B,0 ; LD BC,A - LD HL,CORTAB ; startadres coordinatentabel - ADD HL,BC ; bereken adres in tabel - - - We maken gebruik van een co�rdinatentabel omdat de routine - dan met elke willekeurige grafische karakterset kan worden - gebruikt. We trekken 32 van de ASCII code van het teken af - en vermenigvuldigen dat met twee. Vervolgens tellen we dit - bij het startadres van de tabel op en we hebben het adres in - de tabel waar de co�rdinaten van het desbetreffende teken - staan. - - - LD A,(HL) - LD (COPDAT),A ; SX invullen - INC HL - LD A,(HL) - LD (COPDAT+2),A ; SY invullen - - - Die co�rdinaten worden hier uit de tabel gehaald en in de - copydata gezet. Zoals we gewend zijn werken we weer met een - blokje copydata van 15 bytes. De benodigde gegevens (source, - destination, etc.) kunnen dan zonodig door het programma - worden veranderd en het uitvoeren van het commando door de - VDP is een kwestie van een simpele OTIR. - - - LD HL,COPDAT - LD BC,&H0F9B - WACHT: LD A,2 - CALL RDSTAT ; lees statusregister - BIT 0,A - JR NZ,WACHT - - - Eerst wachten we netjes totdat de VDP klaar is door op bit 0 - van S#2 te testen. Doen we dit niet, dan kan dat vreemde - effecten hebben. Zeker als de routine op een turbo R onder - R800 stand wordt gedraaid, omdat de kans dan groter is dat - de VDP nog niet klaar is met het kopi�ren van de vorige - letter als hij hier is aangeland. De data voor de OTIR - (HL=beginadres, B=aantal bytes, C=I/O poort) zetten we - alvast klaar. - - - DI - LD A,32 - OUT (&H99),A - LD A,17+128 - OUT (&H99),A - EI - OTIR ; voer copy uit - - - Hier schrijven we de waarde 32 naar R#17, hiermee selecteren - we het startregister voor het indirect registers schrijven - van de VDP. Met de OTIR wordt het blokje met copydata naar - Port #3 gestuurd, waardoor deze bytes netjes in de commando - registers (32 t/m 46) terecht komen en de VDP de letter naar - het scherm zal kopi�ren. - - - LD A,(COPDAT+4) ; oude DX - ADD A,6 ; volgende positie - LD (COPDAT+4),A ; nieuwe DX invullen - NXTKAR: POP BC - DJNZ PRINT - RET - - - Hier wordt er 6 bij de x co�rdinaat opgeteld, zodat de - volgende letter netjes naast deze komt te staan. De lus - wordt afgesloten met een DJNZ. - - - ; Statusregister lezen. In: A=register, Uit: A=data - - RDSTAT: DI - OUT (&H99),A - LD A,128+15 - OUT (&H99),A ; selecteer statusregister - NOP ; geef VDP tijd om data - NOP ; klaar te zetten - IN A,(&H99) - EX AF,AF - XOR A - OUT (&H99),A - LD A,128+15 - OUT (&H99),A ; selecteer S#0 - EI - EX AF,AF - RET - - - Dit is een standaardroutine voor het uitlezen van een - statusregister, dit zou u inmiddels zonder verdere uitleg - moeten kunnen begrijpen. - - - COPDAT: DB 0,0,0,3 ; SX en SY (page 3) - DB 0,0,0,0 ; DX en DY (page 0) - DB 5,0,7,0 ; NX en NY - DB 0,0 ; CLR en ARG - DB &B10010000 ; LMMM - - - Dit is het blok met copy data. De pages, grootte en het - commando zijn al ingevuld, door de routine wordt de source - (de letter op page 3) en de destination (waar komt de letter - op page 0) ingevuld. &B10010000 staat voor LMMM, Logical - Move VRAM to VRAM. - - Tot slot de co�rdinatentabel. Dit ziet er misschien een - beetje lang uit, maar het is met een BASIC programmaatje in - een wip aangemaakt. Deze tabel kunt u aanpassen voor elke - gewenste karakterset. - - - ; Coordinaten van ASCII 32 t/m ASCII 93 - - CORTAB: DB 0,197 ; - DB 6,197 ; ! - DB 12,197 ; " - DB 18,197 ; # - DB 24,197 ; $ - DB 30,197 ; % - DB 36,197 ; & - DB 42,197 ; ' - DB 48,197 ; ( - DB 54,197 ; ) - DB 60,197 ; * - DB 66,197 ; + - DB 72,197 ; , - DB 78,197 ; - - DB 84,197 ; . - DB 90,197 ; / - DB 96,197 ; 0 - DB 102,197 ; 1 - DB 108,197 ; 2 - DB 114,197 ; 3 - DB 120,197 ; 4 - DB 126,197 ; 5 - DB 132,197 ; 6 - DB 138,197 ; 7 - DB 144,197 ; 8 - DB 150,197 ; 9 - DB 156,197 ; : - DB 162,197 ; ; - DB 168,197 ; < - DB 174,197 ; = - DB 180,197 ; > - DB 186,197 ; ? - DB 192,197 ; @ - DB 0,205 ; A - DB 6,205 ; B - DB 12,205 ; C - DB 18,205 ; D - DB 24,205 ; E - DB 30,205 ; F - DB 36,205 ; G - DB 42,205 ; H - DB 48,205 ; I - DB 54,205 ; J - DB 60,205 ; K - DB 66,205 ; L - DB 72,205 ; M - DB 78,205 ; N - DB 84,205 ; O - DB 90,205 ; P - DB 96,205 ; Q - DB 102,205 ; R - DB 108,205 ; S - DB 114,205 ; T - DB 120,205 ; U - DB 126,205 ; V - DB 132,205 ; W - DB 138,205 ; X - DB 144,205 ; Y - DB 150,205 ; Z - DB 156,205 ; [ - DB 162,205 ; \ - DB 168,205 ; ] - - - V O O R B E E L D - - Zo, dat was de ML routine. Niet echt moeilijk denk ik. Hij - staat op de disk onder de naam PRTEXT.ASC. Om het uit te - testen gebruiken we het volgende BASIC programma: - - 100 ' PRTEXT voorbeeld - 110 ' Door Stefan Boer, 20/03/93 - 120 ' (c) Ectry 1993 - 130 ' Sunrise Magazine #7 VDP cursus - 140 ' - 150 SCREEN5:COLOR15,0,0:CLS - 160 CLEAR200,&HCFFF:DEFINTA-Z:BLOAD"PRTEXT.BIN": - DEFUSR=&HD000 - 170 OPEN"GRP:"AS1:SETPAGE,3:CLS:A=32:FORI=0TO192STEP6: - PRESET(I,197):PRINT#1,CHR$(A):A=A+1:NEXT: - FORI=0TO168STEP6:PRESET(I,205):PRINT#1,CHR$(A):A=A+1: - NEXT:SETPAGE,0 - 180 FORI=50TO150STEP20:READT$:POKE&HD003,128-3*LEN(T$): - POKE&HD004,I:U$=USR(T$):NEXT - 190 IFSTRIG(0)=0THEN190ELSEEND - 200 DATA "PRTEXT" - 210 DATA " " - 220 DATA "(C) ECTRY 1993" - 230 DATA " " - 240 DATA "VDP CURSUS" - 250 DATA "SUNRISE MAGAZINE #7" - - Dit staat ook op de disk onder de naam PRTEXT.BAS. De - geassembleerde ML file staat er ook op: PRTEXT.BIN. Samen - staan deze files in PRTEXT.PMA. - - Dit voorbeeld is niet bepaald spectaculair, omdat de - standaardkarakterset wordt gebruikt. Wel valt het op dat dit - een stuk sneller is dan OPEN"GRP:"AS1/PRINT#1. Het grote - voordeel hiervan is dat u elk gewenste formaat letters - (zelfs proportioneel als u de routine een klein beetje - aanpast!) kunt gebruiken, ook met meerdere kleuren! - - - T E N S L O T T E - - Een beetje korte tekst dit keer, maar dat hoop ik de - volgende keer goed te maken met een extra lange routine. - - Dit is een leuk voorbeeld om uit te breiden, ik noemde al - een andere (grotere) karakterset of proportioneel schrift. - Zet daarvoor achter de co�rdinaten in de tabel ook de - breedte van de letter, en tel dat getal op bij de oude DX. - - Veel plezier en tot de volgende keer! - - Stefan Boer diff --git a/sunrise_special/7/VDP Cursus 13.md b/sunrise_special/7/VDP Cursus 13.md deleted file mode 100644 index 97264b6..0000000 --- a/sunrise_special/7/VDP Cursus 13.md +++ /dev/null @@ -1,477 +0,0 @@ - M S X 2 / 2 + V D P C U R S U S ( 1 3 ) - - - Bijgelovige mensen moeten dit deel maar overslaan, maar dat - zou zonde zijn want ook dit deel is weer erg leerzaam. Deze - keer behandel ik een ML routine om SCREEN 5 naar SCREEN 8 om - te zetten. Hiervoor is de theorie nodig over het aansturen - van het VRAM en over de opslag van de schermen in het VRAM, - wat uitgebreid in eerdere delen is terug te vinden. Ik zal - het deze keer alleen kort nog even herhalen. - - - S C R E E N 5 N A A R 8 - - - SCREEN 5 en SCREEN 8 hebben dezelfde resolutie, namelijk 256 - bij 212 pixels. Op dat vlak dus geen problemen. Wat er - uiteindelijk moet worden omgezet zijn de kleuren. - - In SCREEN 5 wordt er gewerkt met 16 kleuren uit een palet - van 512, terwijl er in SCREEN 8 slechts 256 kleuren zijn, - die wel allemaal tegelijkertijd op het scherm kunnen worden - getoond. We moeten de 16 SCREEN 5 kleuren dus omrekenen naar - SCREEN 8 kleuren. Hierbij zal wel een klein verschil - ontstaan omdat in SCREEN 8 maar 256 van de 512 verschillende - kleuren precies kunnen worden nagemaakt. Van de overige - kleuren moeten we de kleur nemen die er het dichtst bij in - de buurt komt. - - - P A L E T - - Voor het palet in SCREEN 5 zijn er drie bits voor rood, drie - bits voor groen en drie bits voor blauw. Deze moeten naar de - paletregisters van de VDP worden geschreven (zie hiervoor - deel 1 van de cursus), maar kunnen niet worden gelezen. - - In MSX BASIC is dat opgelost door het palet ook nog eens in - het VRAM op te slaan. In SCREEN 5 staat deze kopie van het - palet vanaf adres &H7680. Omdat het palet 32 bytes lang is, - eindigt het op adres &H769F. Het palet kan bij een SCREEN 5 - plaatje dus als volgt worden meegesaved: - - BSAVE "FILENAAM.SC5",0,&H769F,S - - Als het plaatje weer wordt ingeladen kan het palet dan weer - worden teruggehaald met COLOR=RESTORE. Het palet wordt dan - van het VRAM naar de paletregisters van de VDP gekopieerd. - - De data vanaf adres &H7680 is als volgt opgebouwd: - - MSB 7 6 5 4 3 2 1 0 LSB - - &H7680 0 ----R---- 0 ----B---- palet #0 - &H7681 0 0 0 0 0 ----G---- - &H7682 0 ----R---- 0 ----B---- palet #1 - etc. - - Hierbij staat R voor de rode intensiteit, B voor de blauwe - intensiteit en G voor de groene intensiteit, dit alles 3 - bits dus tussen 0 en 7. - - - S C R E E N 8 K L E U R E N - - In SCREEN 8 is er geen palet, maar kan de kleur rechtstreeks - uit de opslag van het scherm in het VRAM worden afgelezen. - Elke byte is als volgt opgebouwd: - - MSB 7 6 5 4 3 2 1 0 LSB - - ----G---- ----R---- --B-- - - Hierbij staan R, G en B weer voor de rode, groene en blauwe - intensiteit. Het valt meteen op dat er voor blauw slechts - twee bits zijn, zodat dit maar een getal tussen 0 en 3 kan - zijn. Dit is de reden waarom een SCREEN 5 plaatje niet exact - kan worden geconverteerd naar SCREEN 8. - - - B I T M A P - - De opslag van de schermdata in het VRAM gaat bij SCREEN 5 en - 8 volgens de bitmap methode. Voor elk pixel zijn er een - aantal bits gereserveerd, waarin de informatie over dat - pixel staat. Elk pixel heeft z'n eigen bits, waardoor er - geen beperkingen zijn aan het aantal kleuren dat bij naast - elkaar liggende pixels mag worden gebruikt, zoals in - bijvoorbeeld SCREEN 2 en SCREEN 12. - - In SCREEN 5 wordt van elk pixel het paletnummer opgeslagen, - dit is een getal van 0-15 en daarvoor zijn dus 4 bits nodig. - In elke byte staan daarom twee pixels, waarbij het linker - pixel in de hoge nibble (bit 4-7) staat en het rechter pixel - in de lage nibble (bit 0-3). In SCREEN 8 zijn er 8 bits per - pixel nodig, dus staat er in elke byte het kleurnummer van - ��n pixel. - - Nu we alle benodigde informatie over de schermen hebben - kunnen we met de conversieroutine beginnen. Zoals gewoonlijk - is deze in WB-ASS2 geschreven, staat de source in ASCII op - de disk en heb ik de source uitgebreid van extra commentaar - en uitleg voorzien. - - Het inladen van het SCREEN 5 plaatje en het wegschrijven van - het SCREEN 8 plaatje laten we aan BASIC over, dit is - tenslotte geen diskcursus. Op de diskette vindt u in - SC5SC8.PMA een BASIC programma (SC5SC8.BAS), dat de ML file - (SC5SC8.BIN) inlaadt en zorgt voor het inladen en - wegschrijven van de grafische files. Ook de source zit - erbij. - - - ; S C 5 S C 8 . A S M - ; SCREEN 5 omzetten naar SCREEN 8 - ; Stefan Boer, april 1993 - ; (c) Ectry 1993 - ; Sunrise Magazine #8 - ; (c) Stichting Sunrise 1993 - - ; SCREEN 5 plaatje in SCREEN 8 inladen, met palet - ; SC8 plaatje wordt door routine over SC5 plaatje gezet - ; en kan worden gesaved met BSAVE"NAAM.SC8",0,54271,S - - ORG &HD000 - - LD A,(&HF342) ; RAM slot &H4000-&H7FFF - LD H,&H40 - CALL &H24 ; RAM op &H4000 - IN A,(&HFE) ; mapper poort &H8000-&HBFFF - LD (OLDMAP),A ; bewaar mapper instelling - LD A,3 ; selecteer ander RAM - OUT (&HFE),A - - - Op adres &HF342 staat de slot-ID byte van het RAM op - &H4000-&H7FFF (page 1). We gebruiken de BIOS routine ENASLT - (adres &H0024) om op adres &H4000 RAM te zetten in plaats - van de BASIC interpreter. We gebruiken dit RAM om tijdelijk - schermdata in op te slaan. - - Op &H8000 selecteren we een ander gedeelte van de mapper, - zodat het BASIC programma dat daar staat niet wordt - overgeschreven. I/O poort &HFE bepaalt welke mapperpage er - op adres &H8000 staat. - - - ; kopieer SCREEN 5 data van VRAM naar RAM - - LD HL,0 - LD C,0 ; VRAM lezen vanaf adres - CALL SETRD ; &H00000 (bitmap data) - - - De standaardroutine SETRD kennen we nog uit het begin van de - cursus. Deze routine stelt de VDP in om VRAM te lezen vanaf - het adres dat in HL en C staat, hierbij is bit 0 van het C - register het MSB (most significant bit) van het VRAM adres. - HL bevat de rest van het adres. Het beginadres van het - scherm in het VRAM is &H00000. - - - LD DE,&H4000 ; beginadres SC5 data in RAM - LD BC,27136 ; lengte SC5 data (128*212) - - COPY: IN A,(&H98) ; lees byte uit VRAM - LD (DE),A ; sla op in RAM - INC DE - DEC BC - LD A,B - OR C - JP NZ,COPY ; herhaal tot BC=0 - - - Hier wordt de SCREEN 5 data naar het RAM gekopieerd, vanaf - adres &H4000. Een scherm is 212 lijnen hoog en elke lijn - neemt 128 bytes in beslag (256 pixels, twee pixels per - byte), dus de totale lengte van een SCREEN 5 plaatje in het - VRAM is 27136 bytes. - - Met IN A,(&H98) wordt het VRAM gelezen. De VDP verhoogt - daarna zelf het leesadres, zodat de volgende keer - automatisch de volgende byte wordt gelezen. Dit wordt - herhaald totdat het hele plaatje in het RAM staat. - - LD A,B en daarna OR C is een truukje om te kijken of BC al - gelijk is aan 0. - - - ; kopieer palet data van VRAM naar RAM - - LD HL,&H7680 - LD C,0 ; VRAM lezen vanaf adres - CALL SETRD ; &H07680 (palet data) - - LD HL,PALET ; beginadres paletdata in RAM - LD B,32 ; lengte palet data - LD C,&H98 ; Port #0 (VRAM lezen) - INIR ; lees B bytes van poort (C) - ; ; en zet in RAM vanaf HL - - - Hier kopi�ren we de paletdata (die zoals we eerder hebben - gezien vanaf adres &H7680 in het VRAM staat) naar het RAM. - Het SCREEN 5 plaatje moet dus wel met palet zijn weggesaved. - - Met de instructie INIR worden B bytes gelezen van poort (C) - en vanaf (HL) in het RAM gezet. Bij het vorige gedeelte had - het weinig zin om deze instructie te gebruiken, omdat er - toen 27136 bytes moesten worden gelezen en er met INIR maar - maximaal 256 bytes per keer kunnen worden gelezen. Het palet - wordt dus vanaf (PALET) in het RAM gezet. - - [Nvdr. De tekst was langer dan 16 kB, u kunt verder lezen - door de volgende optie in het submenu te kiezen.] - - - - M S X 2 / 2 + V D P C U R S U S ( 1 3 ) - - - [Nvdr. Dit is het tweede gedeelte.] - - - ; Converteer palet naar SCREEN 8 kleuren - - LD B,16 ; 16 paletten om te rekenen - LD HL,PALET - LD DE,COLORS ; beginadres SC8 kleurentabel - PALCNV: LD A,(HL) ; lees eerste byte paletdata - AND &B01110000 ; alleen rood (bit 4-6) - RRCA - RRCA ; verplaats rood naar bit 2-4 - LD C,A - - - Dit is het moeilijkste gedeelte van de routine, hier rekenen - we de 16 paletkleuren om naar SCREEN 8 kleuren. We lezen - eerst een byte, en filteren alleen het rood eruit dat zoals - we eerder gezien hebben op bit 4-6 staat. In de SCREEN 8 - kleurcode moet het rood op bit 2-4 staan, we moeten dit dus - twee posities naar rechts verschuiven. Daarvoor gebruiken we - RRCA, deze instructie roteert het A register naar rechts. - Het resultaat wordt in C bewaart, zodat we later blauw en - groen erbij kunnen zetten. - - - LD A,(HL) - AND &B00000111 ; alleen blauw (bit 0-2) - SRL A ; verplaats blauw naar bit 0-1 - OR C - LD C,A ; rood en blauw samen - - - Op analoge wijze wordt hier het blauw toegevoegd. De - instructie SRL A schuift de bits in het A register een - plaatsje naar rechts, terwijl in bit 7 een 0 wordt gezet. We - kunnen hier geen RRCA gebruiken, omdat bit 0 dan in bit 7 - terecht zou komen, en dat is niet de bedoeling. Met OR C - worden rood en blauw samen in een byte gezet. - - - INC HL - LD A,(HL) - AND &B00000111 ; groen (bit 0-2) - RRCA - RRCA - RRCA ; verplaats groen naar bit 5-7 - OR C - - - Groen staat in de volgende byte. Dit moet eigenlijk 5 - plaatsen naar links worden verplaats, maar 3 plaatsen naar - rechts is natuurlijk precies hetzelfde en is korter. Nu - staat de complete SCREEN 8 kleurcode die overeenkomt met de - SCREEN 5 paletkleur in het A register. Het enige verschil is - dat de blauwe intensiteit nu minder nauwkeurig is. - - - LD (DE),A ; SC8 kleurcode naar tabel - INC HL - INC DE - DJNZ PALCNV - - - De zojuist berekende SCREEN 8 kleurcode wordt in de tabel - gezet, en zo worden alle 16 paletkleuren afgewerkt. We gaan - nu de feitelijke schermdata converteren. - - - ; converteer SCREEN 5 data naar SCREEN 8 - - LD HL,0 - LD C,0 - CALL SETWRT ; VRAM schrijven vanaf &H00000 - - - We beginnen weer met de VDP klaar te zetten voor een VRAM - actie, dit keer schrijven. Hiervoor gebruiken we SETWRT, de - tegenhanger van SETRD. Het SCREEN 8 plaatje wordt op adres 0 - gezet, dus gewoon over het SCREEN 5 plaatje heen. - - - LD DE,&H4000 ; SC5 data vanaf &H4000 in RAM - LD BC,27136 ; aantal te converteren bytes - CONVRT: PUSH BC - LD A,(DE) ; lees SC5 byte (2 pixels) - AND &HF0 ; linker pixel - RRCA - RRCA - RRCA - RRCA ; verplaats naar lage nibble - - - DE bevat het huidige adres in het RAM tijdens het omzetten - en BC het aantal nog te converteren bytes. Hier wordt een - SCREEN 5 byte uit het RAM opgehaald en wordt het linker - pixel eruit gehaald. Het paletnummer van dit pixel staat in - de linker nibble, en die verplaatsen we met 4 RRCA - instructies naar het rechter nibble. Nu kunnen we de - bijbehorende SCREEN 8 kleurcode uit de tabel halen: - - - LD HL,COLORS - LD C,A - LD B,0 - ADD HL,BC ; bereken plaats in tabel - LD A,(HL) ; haal kleurnummer uit tabel - OUT (&H98),A ; schrijf naar VRAM - - - Een ADD HL,A instructie bestaat niet, dus dat doen we via - een klein omweggetje. Tot slot wordt de byte naar het VRAM - geschreven met de OUT (&H98),A instructie. Nu nog het - rechter pixel: - - - LD A,(DE) - AND &H0F ; rechter pixel - LD HL,COLORS - LD C,A - LD B,0 - ADD HL,BC - LD A,(HL) - OUT (&H98),A - - - Dat gaat een stuk makkelijker omdat die al op de goede - plaats staat. Verder is het analoog. - - - POP BC - INC DE - DEC BC - LD A,B - OR C - JP NZ,CONVRT - - - Hier wordt de lus afgesloten, zodat het hele plaatje wordt - geconverteerd. Door de hier gekozen methode gaat dat - razendsnel! Probeer het maar eens, het programma staat - immers niet voor niets op de diskette. - - Het programma is zo snel omdat de SCREEN 5 data eerst in ��n - keer naar het RAM wordt gekopieerd, waardoor de VDP maar ��n - keer hoeft te worden ingesteld om VRAM te lezen, en daarna - slechts Port #0 (&H98) hoeft te worden gelezen. De SCREEN 8 - data wordt ook in ��n keer naar het VRAM geschreven, - waardoor de VDP ook maar ��n keer voor schrijven hoeft te - worden ingesteld. De routine zou veel en veel langzamer zijn - indien er steeds ��n SCREEN 5 byte zou worden gelezen, dan - weer twee SCREEN 8 bytes schrijven, etc. Dan moeten de SETRD - en SETWRT routines namelijk elke keer weer worden - aangeroepen. - - Tot slot moeten we nog even de slot- en mapperschakeling in - de oude toestand herstellen, en een aantal geheugenplaatsen - defini�ren met DB en DS instructies. Op adres &HFCC1 staat - de slot-ID byte voor het MAIN ROM, voor zowel page 0 als - page 1. - - - ; zet geheugen weer terug in oude stand - - LD A,(OLDMAP) - OUT (&HFE),A ; herstel mapper - LD A,(&HFCC1) - LD H,&H40 - CALL &H24 ; BASIC ROM weer op &H4000 - RET - - OLDMAP: DB 1 - COLORS: DS 16 - PALET: DS 32 - - - Tot slot nog de standaardroutines om de VDP klaar te zetten - voor VRAM lezen resp. schrijven. Er staat genoeg commentaar - in de source, voor verdere uitleg verwijs ik u naar het - begin van de cursus. - - - ; 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 - - - G E B R U I K - - Tot slot nog een aantal wenken voor het geval u de converter - wilt gaan gebruiken. Omdat de converter het palet nodig - heeft, moeten de plaatjes met palet zijn weggeschreven, op - de manier zoals eerder in deze tekst vermeld. Indien u - andere files wilt gebruiken (bijvoorbeeld .SR5 en .PL5 van - GraphSaurus), kunt u daarvoor het BASIC programma zelf - aanpassen. - - Het hele programma draait onder SCREEN 8. Als het SCREEN 5 - plaatje wordt ingeladen ziet dit er dus niet uit. Maakt u - zich daarover niet druk, dat hoort dus zo. U zult zien dat - resultaat qua kleur ietsje afwijkt van het origineel, dat - komt zoals eerder gezegd doordat het blauw in SCREEN 8 - minder nauwkeurig kan worden opgegeven. Hierdoor wordt het - plaatje ook iets donkerder. Hier is verder niets aan te - doen. - - Het zal in de praktijk wel eens voorkomen dat u een SCREEN 5 - plaatje naar SCREEN 8 wilt omzetten, bijvoorbeeld als u een - SCREEN 5 plaatje in Dynamic Publisher wilt inladen. DP kan - namelijk alleen SCREEN 8 plaatjes converteren. - - Ook deze keer wens ik u weer veel succes met het toepassen - van het geleerde. Tot de volgende keer! - - Stefan Boer diff --git a/sunrise_special/7/VDP Cursus 14.md b/sunrise_special/7/VDP Cursus 14.md deleted file mode 100644 index 18913d9..0000000 --- a/sunrise_special/7/VDP Cursus 14.md +++ /dev/null @@ -1,174 +0,0 @@ - M S X 2 / 2 + V D P C U R S U S ( 1 4 ) - - - - L I N E - - In BASIC is een lijn trekken erg simpel en behoort het LINE - commando tot de eerste commando's die iedereen kent. In ML - is dat wel anders, want het LINE commando is verreweg het - ingewikkeldste commando van de VDP. - - De theorie is reeds in deel 4 van de VDP cursus behandeld, - maar omdat het toch nog vrij ingewikkeld is om aan de hand - daarvan een eigen lijn routine te schrijven, behandel ik - deze keer een standaardroutine om lijnen te trekken. - - De routine is wel enigszins beperkt, aangezien de co�rdi- - naten maar 8 bits zijn. Hierdoor is de routine minder - geschikt voor SCREEN 6 en 7 en de lijnen kunnen maar in 1 - page worden getrokken. - - Laat ik maar meteen beginnen met de source. - - ; L I N E . A S M - ; Trek een lijn (H,L)-(D,E) - ; Kleur=B; Log. op=A - ; Door Stefan Boer - ; VDP Cursus deel 15 - ; Sunrise Magazine #9 - ; (c) Stichting Sunrise 1993 - - LINE: AND &H0F ; logische operatie - OR &H70 ; line - LD (LINDAT+10),A - LD A,B ; kleur - LD (LINDAT+8),A - LD A,H ; DX - LD (LINDAT),A - LD A,L ; DY - LD (LINDAT+2),A - - Het makkelijkst zijn de kleur, logische operatie en begin- - co�rdinaten. Die kunnen zonder verdere problemen alvast - worden ingevuld. &H70 is de opcode voor line. LINDAT is een - blokje met de 11 bytes die zodadelijk naar de VDP worden - gestuurd (registers 36 t/m 46). - - Nu komen de problemen. Het LINE commando van de VDP werkt - namelijk niet zoals alle andere commando's met NX en NY, - maar met Maj en Min. De lijn wordt gezien als de schuine - zijde van een rechthoekige driehoek, waarbij Maj en Min dan - de twee rechte zijden zijn. Maj is de langste en Min de - kortste. - - Met MAJ (bit 0 van het argument register) moet worden - aangegeven of de langste zijde in de x richting is (0) of in - de y richting (1). Verder moet met DIX en DIY zoals - gewoonlijk worden aangegeven of de lijn vanaf (DX,DY) naar - links/rechts resp. boven/beneden gaat. Je snapt wel dat het - even wat logisch nadenken kost om dit alles te programmeren. - - We gaan nu eerst gewoon de NX berekenen, alsof er niks aan - de hand is. NX moet gelijk zijn aan ABS(x1-x2). - - LD A,H ; x1 - SUB D ; x1-x2 - LD D,&B00000100 ; DIX=links - JR NC,LINE_1 ; x1>x2 - LD D,0 ; DIX=rechts - NEG ; positief maken - LINE_1: LD H,A ; NX - - Behalve NX hebben we nu ook meteen DIX, en wel in bit 2 van - D. NY gaat analoog: - - LD A,L ; y1 - SUB E ; y1-y2 - LD E,&B00001000 ; DIY=omhoog - JR NC,LINE_2 ; y1>y2 - LD E,0 ; DIY=omlaag - NEG ; positief maken - LINE_2: LD L,A ; NY - - Ook hier meteen weer DIY, nu in bit 3 van E. Nu gaan we NX - en NY vergelijken om te kijken welke Min en welke Maj (nee, - dat heeft niets te maken met verkeer en waterstaat) wordt. - NY staat nog steeds in A. - - CP H ; vergelijk NX met NY - LD A,0 ; MAJ=X (XOR A kan niet!) - JR C,LINE_3 ; NX>NY - LD C,L - LD L,H - LD H,C ; verwissel NX en NY - LD A,&B00000001 ; MAJ=Y - - Het wisselen van L en H gebeurt via het C register, omdat er - geen EX L,H instructie bestaat. Normaal gesproken gebruik je - natuurlijk altijd XOR A in plaats van LD A,0, maar hier kan - dat niet omdat dan de uitslag van de CP H wordt gewist. De - XOR A voor de CP H zetten kan ook niet, want we hebben de - waarde van A dan nog nodig voor de vergelijking! A bevat nu - MAJ in bit 0, H bevat Maj en L bevat Min. - - (Nvdr. Het "verlies" van XOR A kan wel goed worden gemaakt - met INC A in plaats van LD A,1.) - - - LINE_3: OR D - OR E - LD (LINDAT+9),A ; Arg - LD A,H - LD (LINDAT+4),A ; Maj - LD A,L - LD (LINDAT+6),A ; Min - - In A zat al MAJ, en daar worden DIX en DIY nu bij geORd. - Samen is dat de juiste waarde voor het argument register. - Tot slot worden Maj en Min nog in LINDAT gezet. We hoeven nu - alleen nog de 11 bytes in LINDAT naar de VDP commando - registers 36 t/m 46 te schrijven, waarbij we natuurlijk - eerst moeten checken of de VDP niet nog bezig is met een - ander commando. - - LD BC,&H0B9B - LD HL,LINDAT - CALL VDPRDY - DI - LD A,36 - OUT (&H99),A - LD A,17+128 - OUT (&H99),A - EI - OTIR - RET - - VDPRDY: LD A,2 - CALL RDSTAT - BIT 0,A - JP NZ,VDPRDY - RET - - 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 - - LINDAT: DB 0,0,0,0,0,0,0,0,0,0,0 - - N.B. De routine zet de lijn nu automatisch in page 0. Wilt u - een andere page, zet die dan op (LINDAT+3). - - - T E N S L O T T E - - De source staat op disk onder de naam LINE.ASC. Het is - natuurlijk ook mogelijk om een 16 bits routine te schrijven, - maar dat is nog een stuk moeilijker dan deze 8 bits routine. - Een korte aflevering dit keer, maar naar ik hoop wel weer - een interessante. De volgende keer ga ik een aantal routines - voor sprites behandelen. Tot dan! - - Stefan Boer diff --git a/sunrise_special/7/VDP Cursus 15.md b/sunrise_special/7/VDP Cursus 15.md deleted file mode 100644 index 8c119ff..0000000 --- a/sunrise_special/7/VDP Cursus 15.md +++ /dev/null @@ -1,405 +0,0 @@ - M S X 2 / 2 + V D P C U R S U S ( 1 5 ) - - - Sunrise Magazine mag dan wel het tweede lustrum vieren, ik - vier met de VDP cursus alweer het derde! Ik had beloofd het - deze keer over sprites te gaan hebben, maar stel dat uit tot - deel 16. - - In plaats daarvan bespreek ik deze keer een routine om - SCREEN 2 naar SCREEN 5 om te zetten, dit naar aanleiding van - een brief van Bert Hoogerdijk uit IJsselstein (zie SRM#9). - Hij gebruikte een zeer langzaam programma (40 minuten per - plaatje!) uit het Belgenblad, en vroeg zich af of het niet - sneller kon. Nou, dat kan! Heeft u ook eens zo'n vraag, - schrijf dan gerust, ik geef graag antwoord! - - - S C R E E N 2 - - Het is alweer een tijdje geleden dat we de opslag van de - schermen in het VRAM hebben behandeld, dus als u het niet - meer weet: zoek het even op in een oud deel van de VDP - cursus. - - Omdat SCREEN 2 vrij ingewikkeld in elkaar zit, leg ik het - hier nog maar eens uit. De beeldinformatie staat bij SCREEN - 2 in drie tabellen: - - patroon generator tabel &H0000-&H17FF (6144 bytes) - patroon naam tabel &H1800-&H1AFF (768 bytes) - kleurtabel &H2000-&H37FF (6144 bytes) - - SCREEN 2 is opgebouwd uit 24 rijen van elk 32 posities, - samen 768 positie. In de naamtabel staat voor elke positie - welk karakter er staat. De vorm en kleur van de karakters - staan in de patroontabel en kleurtabel. - - Om ervoor te zorgen dat er 768 verschillende karakters op - het scherm kunnen staan, is het scherm in drie gedeeltes - verdeeld: - - boven : rij 0 t/m 7 - midden: rij 8 t/m 15 - onder : rij 16 t/m 23 - - Per gedeelte is er een apart gedeelte van de patroon- en - kleurtabel. Een karakter bestaat uit 8x8 pixels. De vorm van - het karakter staat in 8 bytes in de patroontabel en de kleur - in 8 bytes in de vormtabel. In de patroontabel staat een 1 - voor voorgrondkleur en een 0 voor achtergrondkleur, in de - kleurtabel geven de 4 hoge bits de voorgrondkleur aan en de - 4 lage bits de achtergrondkleur. - - - L M M C - - Om de 8x8 karakters op SCREEN 5 te zetten gebruik ik het VDP - commando LMMC, wat staat voor Logical Move CPU to VRAM. U - kunt de werking van dit commando uitgebreid nalezen in een - oud deel van de VDP cursus, maar in het kort komt het hierop - neer: - - - Geef met DX, DY, NX en NY een rechthoek in het VRAM aan - - Stuur de pixels een voor een naar R#44 - - Een klein addertje onder het gras is dat we bij de aanroep - van de routine het eerste pixel al mee moeten geven! Dit - maakt een klein omweggetje in onze routine noodzakelijk. - - Om het palet hoeven we ons geen zorgen te maken, omdat in - SCREEN 2 toch alleen het standaardpalet wordt gebruikt. - - Hoog tijd voor de ML source, die deze keer netjes top down - is geprogrammeerd. Zoals gewoonlijk staat hij in ASCII - formaat op de disk onder de naam SC2SC5.ASC (in de file - SC2SC5.PMA). - - - ; S C 2 S C 5 . A S M - ; Zet SCREEN 2 plaatje om naar SCREEN 5 - ; Door Stefan Boer - ; Sunrise Magazine #10 - ; (c) Stichting Sunrise 1993 - - ; SCREEN 2 plaatje moet bij aanroep in RAM staan - ; op &H9000-&HCFFF, SCREEN 5 moet actief zijn - - - SC2DAT: EQU &H9000 ; adres van SC2 data in RAM - - - ORG &HD000 - - Voor de snelheid laden we het SCREEN 2 plaatje (in feite - gewoon het complete MSX1 VRAM van 16 kB) in het RAM vanaf - adres &H9000, dit kan gewoon met BLOAD"NAAM",&H9000. Het - plaatje staat dan van &H9000 t/m &HCFFF, zodat we de routine - op &HD000 laten beginnen. - - - ; initialisatie - - DI - XOR A - LD (REGEL),A - LD HL,SC2DAT+&H1800 - LD (NAAMAD),HL ; pointer naamtabel - LD IX,FLAG - - - ; hoofdprogramma - - REGLUS: CALL DOREGL ; zet een regel om - LD A,(REGEL) - INC A - CP 24 ; klaar? - JR Z,EINDE - LD (REGEL),A - JR REGLUS ; volgende regel - EINDE: EI - RET - - - Het hoofdprogramma roept voor elke regel een routine aan die - de regel omzet naar SCREEN 5. - - - ; zet een regel om - - DOREGL: XOR A - LD (KOLOM),A ; initialisatie - KARLUS: CALL DOKAR ; zet een karakter om - LD A,(KOLOM) - INC A - CP 32 ; klaar? - RET Z - LD (KOLOM),A - JR KARLUS - - - Ook hier gebeurt nog niets moeilijks, hier wordt voor elk - karakter een routine aangeroepen die dat karakter omzet naar - SCREEN 5. Zoals u ziet wordt precies de volgorde van de - naamtabel aangehouden, dat scheelt rekenwerk. - - - ; zet een karakter om - - DOKAR: LD HL,(NAAMAD) ; adres naamtabel - LD A,(HL) ; nummer uit naamtabel lezen - INC HL - LD (NAAMAD),HL - PUSH AF - CALL GETCAD ; bereken adres in kleurtabel - LD (KLR_AD),HL - POP AF - CALL GETGAD ; bereken adres generator tab - LD (GEN_AD),HL - RES 0,(IX+0) ; 1ste pixel nog niet gedaan - LD B,8 - PIXLUS: CALL DO8PIX ; zet regeltje van 8 pixels om - DJNZ PIXLUS - RET - - - Eerst wordt het nummer van het huidige karakter uit de - naamtabel gehaald. Zoals ik het nu geprogrammeerd heb bevat - (NAAMAD) steeds het adres dat hoort bij KOLOM en REGEL, - waardoor er niet extra gerekend hoef te worden. Bij het - karakternummer worden de bijbehorende adressen in de - patroon- en kleurtabel uitgerekend. - - IX+0 wijst naar een adres waar we met bit 0 bijhouden of het - huidige pixel het eerste pixel is van het huidige 8x8 - blokje. Dit is nodig omdat bij het naar de VDP sturen van - het LMMC commando het eerste pixel al bekend moet zijn. - - Een karakter bestaat uit 8 regels van 8 pixels, in de lus - PIXLUS worden deze 8 regels ��n voor ��n omgezet. - - - ; Bereken adres in kleurtabel - ; In : A=karakternummer - ; Uit: HL=adres - - GETCAD: LD L,A - LD H,0 - ADD HL,HL - ADD HL,HL - ADD HL,HL ; *8 - LD DE,SC2DAT+&H2000 - ADD HL,DE - LD A,(REGEL) - CP 8 - RET C ; bovenste gedeelte - LD DE,&H0800 - ADD HL,DE - CP 16 - RET C ; middelste gedeelte - ADD HL,DE ; onderste gedeelte - RET - - - Eerst wordt 8*A uitgerekend en in HL gezet. Vervolgens wordt - het beginadres van de kleurtabel (die in dit geval in het - RAM staat vanaf adres &H9000!) uitgerekend. Tot slot wordt - gekeken in welk gedeelte van het scherm we ons bevinden, en - wordt er indien nodig ��n (middelste gedeelte) of twee maal - (onderste gedeelte) &H800 bij het adres opgeteld. - - - ; Bereken adres in patroon generator tabel - ; In: A=karakternummer - ; Uit: HL=adres - - GETGAD: LD L,A - LD H,0 - ADD HL,HL - ADD HL,HL - ADD HL,HL ; *8 - LD DE,SC2DAT - ADD HL,DE - LD A,(REGEL) - CP 8 - RET C ; onderste gedeelte - LD DE,&H0800 - ADD HL,DE - CP 16 - RET C ; middelste gedeelte - ADD HL,DE ; onderste gedeelte - RET - - - Deze routine is bijna gelijk aan de vorige, het enige - verschil is dat het beginadres van de patroontabel &H0000 is - in plaats van &H2000. - - - ; Zet een rijtje van 8 pixels om - - DO8PIX: CALL GETCOL ; lees kleuren - CALL GETBYT ; lees een byte v/h karakter - PUSH BC - LD B,8 - DOPIX: LD A,D ; voorgrondkleur - RL C - JR C,DOPIX2 - LD A,E ; bit 0, dus achtergrond kleur - DOPIX2: BIT 0,(IX+0) ; flag eerste pixel - JR Z,FSTPIX - OUT (&H9B),A ; pixel naar VDP - DJNZ DOPIX - POP BC - RET - FSTPIX: CALL SETVDP ; 1ste pixel, commando n. VDP - DEC B - JR DOPIX - - - Dit gedeelte doet het eigenlijke omzetwerk. Eerst worden de - gegevens van het huidige rijtje van 8 pixels uit de kleur- - en patroontabel gelezen (GETCOL en GETBYT). De kleuren staan - nu in D en E en de 'vorm' in C. Vervolgens schuiven we de - bits van C ��n voor ��n in de carry, omdat we dan makkelijk - kunnen testen. Is het bit 1 dan sturen we de voorgrondkleur - naar de VDP en is het bit 0 dan sturen we de - achtergrondkleur naar de VDP. - - Voor het schrijven naar R#44 gebruiken we indirecte - adressering zonder auto increment, wat erop neer komt dat we - de kleuren gewoon achter elkaar naar poort #3 (I/O adres - &H9B) kunnen sturen, zoals hier ook gebeurt. - - Ik heb het al eerder gehad over het addertje onder het gras - met LMMC, we moeten bij het geven van het commando de kleur - van het eerste pixel al meegeven. Daarvoor dient de - instructie met bit 0 van (IX+0). Bij het eerste pixel wordt - de routine SETVDP aangeroepen in plaats van dat het gewoon - naar &H9B wordt geschreven. - - - ; Lees kleuren - ; Uit: E=achtergrondkleur, D=voorgrondkleur - - GETCOL: LD HL,(KLR_AD) - LD A,(HL) - INC HL - LD (KLR_AD),HL - PUSH AF - AND &H0F - LD E,A ; achtergrondkleur - POP AF - AND &HF0 - RRCA - RRCA - RRCA - RRCA - LD D,A ; voorgrondkleur - RET - - - Deze routine leest een byte uit de kleurtabel en zet de - voorgrond- en achtergrondkleur in respectievelijk D en E. - - - ; Lees een byte van het karakter - ; Uit: C=byte - - GETBYT: LD HL,(GEN_AD) - LD C,(HL) - INC HL - LD (GEN_AD),HL - RET - - - Deze routine leest een byte uit de patroontabel, dit is een - stuk simpeler omdat er verder niets meer hoeft te worden - gerekend. - - De nu volgende routine wordt steeds voor elk 8x8 blokje - aangeroepen zodra de kleur van het eerste pixel bekend is. - De VDP wordt klaargezet om een blokje van 8x8 pixel voor - pixel te vullen, waarbij de data naar &H9B moet worden - geschreven. - - - ; Zet VDP klaar om SCREEN 5 data te ontvangen - ; In: A=kleur van eerste pixel - - SETVDP: EX AF,AF - LD A,36 - OUT (&H99),A - LD A,17+128 - OUT (&H99),A ; 36 --> R#17 - - LD A,(KOLOM) - RLCA - RLCA - RLCA ; *8 - OUT (&H9B),A ; DX - XOR A - OUT (&H9B),A - LD A,(REGEL) - RLCA - RLCA - RLCA ; *8 - OUT (&H9B),A ; DY - XOR A - OUT (&H9B),A - - LD A,8 - OUT (&H9B),A ; NX - XOR A - OUT (&H9B),A - LD A,8 - OUT (&H9B),A ; NY - XOR A - OUT (&H9B),A - - EX AF,AF - OUT (&H9B),A ; kleur eerste pixel - XOR A - OUT (&H9B),A ; ARG - LD A,&HB0 ; LMMC - OUT (&H9B),A ; commando - - LD A,44+128 ; zonder auto increment naar - OUT (&H99),A ; R#44 schrijven - LD A,17+128 - OUT (&H99),A ; 44+128 --> R#17 - - SET 0,(IX+0) ; flag eerste pixel gedaan - RET - - - Het valt je misschien op dat ik helemaal niet controleer of - de VDP wel klaar is met het vorige commando. Dat is hier - niet nodig, want de VDP is zo snel dat zelfs de R800 het - niet kan bijhouden met het rekenwerk. Het checken op het - Command Execute bit heeft dus geen zin en zou de routine - alleen onnodig vertragen. - - - ; variabelen - - REGEL: DB 0 ; huidige regel - KOLOM: DB 0 ; huidige kolom - FLAG: DB 0 ; flag eerste pixel gedaan - NAAMAD: DW 0 ; huidig adres in naamtabel - KLR_AD: DW 0 ; huidig adres in kleurtabel - GEN_AD: DW 0 ; in pattern generator tabel - - - Tot slot wordt ruimte geserveerd voor de opslag van de - benodigde variabelen. - - - T E N S L O T T E - - In SC2SC5.PMA zitten verder nog SC2SC5.BIN, SC2SC5.BAS en - NEMESIS.VRM, waarmee u de routine even kunt uitproberen (de - .BAS file RUNnen). U zult zien dat het zeer snel gaat! - - Tot de volgende keer, - Stefan Boer diff --git a/sunrise_special/7/VDP Cursus 16.md b/sunrise_special/7/VDP Cursus 16.md deleted file mode 100644 index 449892a..0000000 --- a/sunrise_special/7/VDP Cursus 16.md +++ /dev/null @@ -1,251 +0,0 @@ - - M S X 2 / 2 + V D P C U R S U S ( 1 6 ) - - - Ik zal de spritefans ook deze keer weer teleurstellen, want - ik kreeg naar aanleiding van mijn oproep om met vragen te - komen een vraag van een lezer hoe je het 'Xak effect' in ML - maakt. De spritefans hoeven zich niet gelijk voor de trein - te gooien, want op Sunrise Special #5 geeft R�man v/d - Meulen, een van de programmeurs van Fuzzy Logic, zijn - geheimen op spritegebied prijs. - - - X A K E F F E C T - - Er zijn misschien lezers die nu met opgetrokken wenkbrauwen - voor de monitor zitten. Xak effect? Wat is dat? In de demo - van Xak The Tower of Gazzel zit een heel mooi effect, het - lijkt erop alsof het woord Xak op het scherm wordt - 'gegoten'. Als u het nog nooit gezien heeft, bekijk dan maar - het voorbeeld van de routine die ik deze keer ga bespreken - door XAK.BAS te RUNnen. Alle files behorende bij dit artikel - zitten in XAKEFFCT.PMA. - - Hoe werkt het nu precies? Stel het plaatje moet uiteindelijk - vanaf lijn 100 op het scherm komen te staan. Dan kopieer je - eerst de eerste lijn van het plaatje naar lijn 211 t/m 100, - daarna de tweede lijn naar lijn 211 t/m 101, etc. - - Voor het voorbeeld gebruiken we het logo van Overflow!, zie - de rubriek Backgrounds voor meer informatie over deze groep. - Dit logo is 102 lijnen hoog. Om te zorgen dat het restje aan - het eind wordt uitgewist, nemen we een extra zwarte lijn - onderaan het plaatje mee, waardoor het totaal op 103 komt. - We zetten het plaatje bovenaan op page 1, en we willen dat - het midden op page 0 terecht komt. - - Als je het Xak effect nu zonder verder nadenken in BASIC zou - programmeren voor dit logo, krijg je ongeveer zoiets: - - FOR I=0 TO 102 - FOR Y=211 TO 55+I STEP -1 - COPY (0,I)-(255,I),1 TO (0,Y) - NEXT - NEXT - - De I-lus gaat het plaatje lijn voor lijn af, de Y lus - kopieert die lijn van onderaf tot aan de juiste positie. Als - je FOR Y=55+I TO 211 zou doen, dan zou je het er heel stom - uitzien, omdat het kopi�ren dan tegen de 'gietrichting' in - gaat. - - Dit gaat in BASIC niet vloeiend, en ook in ML niet echt. Het - kan veel handiger door de VDP het vuile werk op te laten - knappen. Het kan met slechts twee copy's per lijn!!! - - - S L I M W I S S E N - - Het lijkt of ik nu naar een heel onderwerp ga, maar dat is - toch niet zo. Als je in ML een gebied vanaf Begin met lengte - Lengte met de waarde Waarde wilt vullen, dan doe je dat zo: - - LD HL,Begin - LD DE,Begin+1 - LD BC,Lengte-1 - LD (HL),Waarde - LDIR - - Dit gaat zo. Je zet zelf de waarde al op het begin. De Z80 - (of R800) leest (Begin) en zet die waarde op (Begin+1). - Daarna leest hij (Begin+1) en zet die waarde op (Begin+2), - etc. Zo wordt dus het hele gebied met de juiste waarde - gevuld! - - - E N N U I N M L - - Dit truukje gebruiken we ook bij het Xak effect. We kopi�ren - de lijn maar ��n keer, en wel naar (0,211). Daarna kopi�ren - we een blok van de juiste hoogte van (0,211) naar (0,210) - [een blok dat naar boven is gericht]. De VDP kopieert eerst - lijn 211 op lijn 210, daarna lijn 210 op 209, etc. Precies - wat we willen hebben! - - In ML ziet dit er als volgt uit: - - - ; Xak effect - ; XAK.GEN - ; Door Stefan Boer - ; VDP Cursus Sunrise Magazine #11 - ; (c) Stichting Sunrise 1994 - ; v1.0 20/01/94 - - Bron_X: EQU 0 - Bron_Y: EQU 0 - Bron_Page: EQU 1 - Doel_X: EQU 0 - Doel_Y: EQU 55 - Doel_Page: EQU 0 - Breedte: EQU 256 - Hoogte: EQU 103 - - - Om ervoor te zorgen dat de routine universeel bruikbaar is - gebruik ik voor alle gegevens betreffende het plaatje EQU's. - X-co�rdinaten en Breedte worden als words behandeld, zodat - de routine ook voor SCREEN 7 en voor plaatjes van 256 breed - (SCREEN 5 over de hele breedte) geschikt is. - - - DB #FE - DW Start - DW Einde - DW Start - - - Dit is de .BIN header voor GEN80, die WB-ASS2 gebruikers - kunnen overslaan. - - - ORG #D000 - - Start: LD HL,Copy_Lijn - CALL DoCopy - - LD HL,Copy_Effect - CALL DoCopy - - LD A,(Copy_Effect+10) ; Hoogte - DEC A - LD (Copy_Effect+10),A - - LD A,(Copy_Lijn+2) ; Bron_Y - INC A - LD (Copy_Lijn+2),A - - CP Bron_Y+Hoogte ; klaar? - JR NZ,Start - - RET - - - Ja, dit is het hele hoofdprogramma. Gewoon twee copy's. Bij - Copy_Lijn wordt steeds de lijn verhoogd die wordt - gekopieerd, en bij Copy_Effect wordt steeds de hoogte van - het blok met ��n verkleind. - - - Copy_Lijn: DW Bron_X - DB Bron_Y,Bron_Page - DW Doel_X - DB 211,Doel_Page - DW Breedte,1 - DB 0,0,#D0 - - Copy_Effect: DW Doel_X - DB 211,Doel_Page - DW Doel_X - DB 210,Doel_Page - DW Breedte,210-Doel_Y - DB 0,8,#D0 ; DIY = 1 - - - Dit zijn de data's voor de copy's, waarbij zoals ik al had - gezegd alles wat met X te maken heeft met DW's is gedaan - zodat de routine universeel bruikbaar is. Ik gebruik hier de - High Speed copy (#D0), dus let erop dat de x-co�rdinaat even - moet zijn in SCREEN 5. DIY = 1 bij de tweede copy, zodat er - van onder naar boven wordt gekopieerd. - - Nu volgen nog de standaardroutines DoCopy, ReadStatus en - VDPReady, die inmiddels bekend worden verondersteld. - - - ; ---------------------------------------------------------- - ; DoCopy - ; Voer VDP commando uit - ; In : HL = startadres 15 bytes - ; Gebruikt: AF, HL, BC - ; ---------------------------------------------------------- - - DoCopy: CALL VDPReady - DI - LD A,32 - OUT (#99),A - LD A,17+128 - OUT (#99),A - EI - LD BC,#0F9B - OTIR - RET - - - ; ---------------------------------------------------------- - ; VDPReady - ; Wacht tot VDP klaar is met commando executie - ; Gebruikt: AF - ; ---------------------------------------------------------- - - VDPReady: LD A,2 - CALL ReadStatus - BIT 0,A - JR NZ,VDPReady - RET - - - ; ---------------------------------------------------------- - ; ReadStatus - ; Lees VDP statusregister - ; In : A = nummer van te lezen statusregister - ; Uit : A = data - ; Gebruikt: AF' - ; ---------------------------------------------------------- - - ReadStatus: DI - OUT (#99),A - LD A,15+128 - OUT (#99),A - NOP - NOP - IN A,(#99) - EX AF,AF' - XOR A - OUT (#99),A - LD A,128+15 - OUT (#99),A - EI - EX AF,AF' - RET - - Einde: END - - - T E N S L O T T E - - Op de disk staan XAK.GEN, XAK.BAS, XAK.BIN en OVERFLOW.SC5 - (in de file XAKEFFCT.PMA). U kunt de routine uitproberen - door XAK.BAS te RUNnen, het Overflow! logo wordt dan op het - scherm 'gegoten'. - - Als er nog meer lezers zijn die iets te vragen op VDP - gebied, schrijf het me dan! Anders is dit het laatste deel - van de VDP cursus. - - Stefan Boer - - P.S. Ik begin binnenkort met een V9990 cursus, daarop kan - dit effect natuurlijk ook worden gemaakt, alleen dan - nog spectaculairder! diff --git a/sunrise_special/7/Valburg reactie.md b/sunrise_special/7/Valburg reactie.md deleted file mode 100644 index 15f6e1d..0000000 --- a/sunrise_special/7/Valburg reactie.md +++ /dev/null @@ -1,257 +0,0 @@ - V A L B U R G R E A K T I E - - - Ik ben geroerd. Tegen mijn verwachting in heeft iemand (Jan - van Valburg) de moeite genomen om eens te reageren op ��n - van mijn literaire brouwsels (Sunrise Special #6). Dankjewel - Jan, het komt namelijk zelden tot nooit voor dat er reakties - komen op artikelen die door het gilde van Sunrise - medewerkers geschreven worden, wat wij overigens zeer jammer - vinden. Het lijkt wel alsof alle abonnementen van de Special - op kerkhoven worden bezorgd wat de stilte van de kant van de - lezers zou verklaren. - - Daar komt nog bij dat het artikel van Jan de 'totaal andere - aanpak' een uitermate frisse kijk geeft op een manier van - programmeren die zijn vruchten sinds het CP/M tijdperk heeft - afgeworpen. Jan omschrijft in zijn artikel het bijhouden van - een standaard kernel als leuk en interessant, maar weinig - nuttig en dat kan ik natuurlijk niet zomaar over mijn kant - laten gaan. Dergelijke uitspraken schreeuwen om een - weerwoord, maar daarover later meer. - - - D E B E S T E O N T W I K K E L O M G E V I N G - - Laat ik beginnen met het introduceren van twee termen die - nogal eens zullen vallen in de rest van dit artikel. Een - programmeeromgeving definieer ik als de feitelijke assembler - of compiler, met eventueel in combinatie een linker en - librarian (een programma dat libraries onderhoud). Met een - ontwikkelomgeving bedoel ik alle andere software die - daarnaast nog nodig is, zoals een editor, een debugger, een - RAMdisk en (heel belangrijk) het Operating System. - - Iemand die een softwareprojekt aan het uitwerken is waarbij - een aanzienlijke hoeveelheid code en data komt kijken heeft - behoefte aan een goede ontwikkelomgeving. Deze omgeving moet - ondersteunend werken wat zoveel betekent als het voorkomen - van ergernissen die in principe niets met het projekt te - maken hebben. Denk hierbij aan resource (geheugen, - diskruimte etc.) conflicten tussen de compiler en het - project. Ook het omschakelen tussen programmeeromgeving en - het programma zelf moet vlekkeloos en snel gaan. - - DOS kan als ontwikkelomgeving gebruikt worden. Het hele - concept van DOS draait om een 'single user / single process' - omgeving. Op ��n moment kan er dus maar 1 programma draaien, - door ��n gebruiker. Dat betekent dus dat bv. een assembler - en linker niet tegelijkertijd aktief kunnen zijn tenzij ze - onderdeel zijn van hetzelfde programma. Indien je geen - Harddisk hebt is dit een hel, omdat de ontwikkelomgeving - plotseling tegen je werkt door fikse tijdsvertragingen te - introduceren. - - Jan noemt in zijn artikel een bij hem ontwikkelde aversie - tegen WB-ASS2 en ik begrijp dat best. GEN80 in combinatie - met een Linker en Librarian is inderdaad heel, heel veel - beter. Indien je daarnaast echter niet de beschikking hebt - over een turbo R met Harddisk worden deze voordelen teniet - gedaan door de enorme traagheid van de omgeving. Jan noemt - dit niet met zoveel woorden, maar ik kan uit zijn artikel - opmaken dat hij er net zo over denkt (denk ik). Een RAMdisk - biedt daarbij niet zoveel soelaas omdat je dan nl. erg - voorzichtig moet zijn met welk geheugen je gebruikt. - - Aangenomen dat je in het bezit bent van een super MSX- - configuratie, dan nog stuit ik op ��n aanzienlijk nadeel van - de GEN80 / DOS omgeving. De assembler, de linker en de - librarian (de programmeeromgeving) vormen samen een redelijk - nauw samenwerkend geheel. Ze begrijpen elkaars in- en - uitvoer prima waardoor de gebruiker hier geen enkel probleem - zal tegenkomen. Elk ander onderdeel van de omgeving (editor - en debugger) is echter niet verwant aan de andere - programma's. Dat hoeft op zich geen probleem te zijn en het - zal op MSX nauwelijks voor problemen zorgen, maar het - beperkt de theoretische mogelijkheden toch wat. - - Waarom is de assembler van WB-ASS bv. zo snel? Het antwoord - schuilt in de aanverwante editor. Deze produceert nl. geen - ASCII bestanden, maar een getokeniseerde versie zoals BASIC. - De assembler kan zijn werk veel sneller doen doordat er in - de editor reeds een vorm van 'pre-processing' is gedaan. Het - zijn dit soort 'kleine' dingen die een ontwikkelomgeving tot - ongekende doelmatigheid doen stijgen. WB-ASS2 mag dan zijn - nadelen en beperkingen hebben, maar de combinatie - editor/assembler levert aanzienlijke tijdwinsten tijdens het - assembleren die met GEN80 onmogelijk te halen zijn. - - Ik kan het niet laten om hier ook even bij andere - computersystemen stil te staan. Overal om me heen zie ik - advertenties in bladen die een samensmelting van - programmeer- en ontwikkelomgeving propageren. Een uitstekend - voorbeeld is bv. Borland-C voor de PC. - - Borland-C is een ge�ntegreerde C++ compiler met de editor, - compiler, linker en librarian in ��n programma. - Voordelen: - - De editor is zeer geschikt om programma's mee te schrijven - - De linker in nagenoeg onzichtbaar voor de gebruiker omdat - alles automatisch gaat. - - Dit geldt ook voor de librarian - - De ontwikkelde software werkt voor het oog van de gebrui- - ker vlekkeloos met de omgeving samen. De gebruiker hoeft - bv. niet zelf tussen verschillende programma's heen en - weer te springen. - - Nadelen: - - Het is een drug, want je wilt nooit meer iets hebben dat - minder lekker werkt (alhoewel er wel betere C compilers - zijn). - - Om nog eens aan te tonen wat ik bedoel zal ik nog een - voorbeeld geven van de enorme invloed die een kleine ingreep - kan hebben. In Borland-C kunnen meerdere listings - tegelijkertijd open staan. Deze listings staan in vensters - die je met de muis kunt besturen. Op het moment dat je het - programma verlaat kan je het programma opdracht geven om de - 'desktop' te saven. Alle posities van vensters en inhoud - worden op deze manier bewaard. Start je het programma nu - opnieuw op, dan wordt de situatie van voor het afsluiten - hersteld en kan je meteen verder werken. Natuurlijk zou het - niet veel tijd kosten om al die bestanden weer even met het - handje te openen, maar daar wordt je behoorlijk moe van na - 30 keer. Een uiterst kleine geste van het programma kan dus - een grote invloed op de funktionaliteit van het geheel - hebben. - - - T O D O S O R N O T T O D O S - - Wat is nu het fundamentele verschil tussen de beste DOS - assembler (GEN80) en de beste BASIC assembler (WB-ASS)? Het - antwoord luidt, de bron en bestemming van data. GEN80 moet - en zal een file als input hebben en genereert ook alleen - maar files als uitvoer. WB-ASS is wat dat betreft veel - flexibeler, maar je kunt praktisch stellen dat WB-ASS - geheugen als invoer neemt en geheugen of een file als - uitvoer heeft. - - Wat is nu het fundamentele verschil tussen DOS en BASIC? Het - antwoord luidt hier dat DOS programma's op een vast adres - laadt en de gebruiker bij BASIC alles zelf maar uit moet - zoeken. Dat eist in de eerste plaats een behoorlijke kennis - van de gebruiker (lijkt me niet onredelijk om dat van een - programmeur te vragen), maar cre�ert ook een waanzinnige - flexibiliteit en controlevermogen over de inhoud van het - geheugen. Nadeel is wel dat dit controlevermogen maar zover - reikt als de kennis van de gebruiker over de gebruikte - programma's. - - Stel dat bv. TED of DD-Graph vanuit BASIC opgestart zouden - kunnen worden en je deze programma's in combinatie met - WB-ASS tegelijkertijd in het geheugen wilt hebben om er - zonder te laden mee te kunnen werken. Dat lukt alleen - wanneer je heel precies zou weten welk geheugen de - respektievelijke programma's gebruiken. Conclusie: met het - hudige Operating System van MSX is dit praktisch onmogelijk. - Dat wil niet zeggen dat het een onoplosbaar probleem is, - maar helaas voor MSX is het te laat. Het zou nl. een - allesomvattend geheugenbeheer programma moeten krijgen dat - onlosmakelijk met het Operating System is verbonden. - - Nu komt daar toch heel stiekem de door Jan afgeraden Kernel - om de hoek kijken. De door ons geschreven F-Kernel (want zo - heet het ding) heeft integraal geheugenbeheer en al onze - programma's houden er rekening mee. Dat betekent praktisch - dat geheugen niet zomaar genomen kan worden, maar dat het - netjes aangevraagd moet worden. Dat lijkt omslachtig en - i.v.m. vaste adressen in code ook heel onhandig, maar ik kan - uit ervaring meedelen dat het juist het omgekeerde is. - WB-ASS is daarbij zo verbouwd dat het vlekkeloos met de - F-Kernel samenwerkt. Andere programma's kunnen natuurlijk - niet zomaar opgestart worden (misschien een idee voor de - toekomst), maar dat is niet anders. - - Ondertussen groeit het aantal programma's dat van de - F-Kernel gebruik maakt gestaag. Utilities en uitbreidingen - van het Operating System zelf; allen houden ze zich netjes - aan de afspraken en kunnen zonder problemen in combinatie - met andere F-Kernel programma's in het geheugen aanwezig - zijn. Het heeft natuurlijk veel werk gekost om dit alles te - bereiken, maar het verandert een MSX met een aanzienlijke - hoeveelheid geheugen in een ware tovermachine. Dat neemt - niet weg dat het feest pas compleet is wanneer we ook een - assembler hebben met betere mogelijkheden. - - De F-Kernel is niet een file met een hoop standaard routines - die je net zo goed in een library kunt stoppen, maar een - Operating System met een specifiek doel dat de hele computer - naar zijn hand zet en integratie van projekt en - ontwikkelomgeving mogelijk maakt. - - In dit verband ben ik ook uitermate benieuwd naar de - aangekondigde assembler van Compjoetania (Compass) die de - voordelen van WB-ASS en GEN80 zou moeten gaan combineren. - Indien dit een pakket wordt dat van de specifieke - mogelijkheden van MSX gebruik maakt, met alle mogelijkheden - van GEN80 en L80 waarbij in het geval van DOS2 netjes met - geheugen wordt omgesprongen etc. dan kan het niet anders dat - straks iedere zichzelf respekterende programmeur hiermee zal - werken. [Nvdr. Helaas, linken is (nog?) niet mogelijk met - Compass.] Heerlijk, een file laden door alleen de muis te - besturen via pull-down menu's. Debug faciliteiten waarmee - tussentijdse breakpoints gezet kunnen worden waardoor het - debuggen van kleine routines in een groter geheel doodsimpel - wordt. - - Alweer hoor ik mensen klagen: "Ja maar dat kost veel teveel - geheugen". Onzin, een programma kan niet teveel geheugen - kosten. Het is een historisch feit dat programmeurs altijd - meer geheugen moeten hebben als dat het te schrijven - programma nodig heeft en dus is dit geen bezwaar. De tijd - dat een MSX met 128kB voldoende zou zijn is voorbij. Om echt - lekker uit de voeten te kunnen is 512kB toch zeker nodig. - Dit natuurlijk wel in combinatie met programma's die weten - hoe ze met geheugen om moeten gaan. - - Zou ik mijn geluk kunnen rekken door de heren van - Compjoetania te vragen alvast hun visie op het te ontstane - produkt toe te lichten ? Indien jullie dat doen dunkt me dat - een aanzienlijke hoeveelheid Special lezers (moi incluis) de - volgende keer watertandend het desbetreffende artikel zullen - verslinden, uitprinten en inlijsten. - - - T O T S L O T - - Jan beveelt (wat een dwingend woord eigenlijk) het gebruik - van GEN80 met de alleskunnende linker aan. Ik deel die - mening, maar alleen zolang je een turbo R met Harddisk hebt. - In alle andere gevallen moet je het zelf maar weten. Wij van - Fuzzy Logic hebben gekozen voor een door ons behoorlijk - verbouwde versie van WB-ASS (Shadow voegt tegenwoordig al - eigen commando's aan WB-ASS toe) waarmee we in combinatie - met onze F-Kernel minstens zo lekker werken als anderen met - GEN80. - - Jan (en natuurlijk ook vele anderen) gebruiken een externe - linker waarmee zowel code als data aan elkaar kunnen worden - geknoopt. De F-Kernel is nog niet zo ver en kan alleen maar - data aan elkaar linken, maar we zijn op de goede weg. - - Jan heeft nooit niet gebruikte routines in zijn programma's - en wij wel, maar dat zal de gemiddelde koper van software - een rotzorg zijn. - - Indien het produkt van de heren van Compjoetania echt goed - wordt en een zeer volledig uitgevoerde ontwikkelomgeving - cre�ert, dan schakelen wij ongetwijfeld over. Het zijn nl. - niet de mogelijkheden van de programmeeromgeving die - doorslaggevend zijn voor de keuze van een pakket, maar de - mogelijkheden en handigheid van de ontwikkelomgeving. - Flexibliteit van de laatst genoemde is daarbij van - essentieel belang omdat iedereen zijn eigen inhoud aan de - omgeving moet kunnen geven. - - Alex van der Wal