MUIZENISSEN Het valt me telkens weer op dat er op MSX maar weinig gebruik gemaakt wordt van de muis. Dit in tegenstelling tot andere systemen waar de muis een absolute noodzaak is geworden. Het is dan ook een heel slim apparaatje dat een gigantische brug kan slaan tussen de software en de gebruiker. Het is toch fantastisch dat er zo'n doosje is dat als je het beweegt een gelijksoortige beweging van een voorwerp op het scherm teweeg brengt! DE GESCHIEDENIS De muis is n van de belangerijkste computerontwikkelingen van de afgelopen 15 jaar. Voorheen moesten alle commando's domweg ingetikt worden en dat maakte de computer niet echt toegankelijk voor het grote publiek omdat de besturing van die dingen alleen maar door een klein elitair groepje mensen gedaan kon worden. Daar is met de komst van de muis nu een radikaal einde aan gekomen. De muis is zelfs zo 'makkelijk' dat een kind dat nog maar amper praten al met een computer overweg kan omdat de besturing zo eenvoudig is geworden. De muis op zich is niet duur, maar de verdere (grafische) weergave bleek ontzettend duur te zijn. Daar kwam pas verandering in toen computers goedkoper werden omdat de produktie omhoog ging. Plotseling werden massaal video kaarten (en losse VDP's) gemaakt die de muis nu ook voor het grote publiek toegankelijk maakten. DE MUIZEN VAN NU Nu, zoveel jaar later kost een muis niet meer dan 150 gulden. Er zijn muizen in alle soorten en maten en er is gelukkig een zekere standarisatie van aansluiting. Natuurlijk had IBM in haar oneindige wijsheid besloten om de zaken zo aan te pakken dat er een behoorlijke connector voor nodig is om een muis aan een PC te hangen, maar er waren gelukkig ook verstandige mensen die de muis gewoon aan de bekende 'Joystick' poort connector gehangen hebben. Bij mijn weten gebruiken MSX, Amiga en Atari deze connector en ze zijn ook volledig uitwisselbaar (alhoewel de standaard meegeleverde muizen van de laatste twee matig tot slecht van kwaliteit zijn). DE WERKING Er zijn ruwweg 3 soorten muizen, waarvan er twee weer op elkaar lijken, nl: - de elektro mechanische muis - de opto mechanische muis - de optische muis De eerste vorm is meteen ook de oudste en gebruikt het overbekende 'balletje tegen asje' systeem. Aan die twee assen zitten echter twee pot-meters (variabele weerstand) die 360 graden kunnen draaien. Door nu de weerstand te meten kon de positie van de muis berekend worden. Deze vorm had echter als nadeel dat het balletje makkelijk over de as gleed waardoor de as niet draaide. Dit slippen werd weer veroorzaakt doordat de pot-meter teveel wrijvingsweerstand genereerde. Verder sleten de pot-meters snel waardoor de weerstandsmeting niet meer goed ging. Deze muizen worden tegenwoordig niet meer gemaakt en wie er n heeft moet dat ding maar in de kast leggen, want het kon wel eens een museumstuk worden. De tweede soort muis is de meest gebruikte muis, en werkt precies hetzelfde als de eerste vorm met het verschil dat de pot-meters vervangen zijn door twee 'wieltjes' met gaten. Affijn, omdat de meeste mensen de rest van de werking wel weten zal ik er verder geen woorden over vuil maken. Het voordeel van deze muis boven de eerste is dat hij niet slijt en dat er heel weinig wrijvingsenergie op de asjes komt. Deze eerste twee vormen hebben echter een gezamelijk nadeel; als ze vuil worden gaan ze haperen (oftewel wrijving). Dit nadeel is opgelost met de komst van de volgende generatie muizen, de optische muis. Deze muis heeft geen bewegende onderdelen en wrijving heeft dus geen invloed op de prestaties. Het komt er op neer dat er in de muis een lichtje brandt samen met een element dat licht opvangt. De muis wordt bewogen over een mat met horizontale en vertikale lijnen die licht weerkaatsen. Affijn, als het licht weerkaatst vangt het andere element het op en zo herkent de muis dat hij beweegt. Al deze muizen werken echter wel met het principe dat ze verplaatsing meten en niet plaats. Ze leveren dus de afgelegde afstand tussen twee metingen aan de computer af die deze meting dan in een positie omzet. Dit gebeurd door de afstand bij de vorige positie op te tellen. DE MUIS LEESAKTIE Er is in het verleden nogal wat verwarring geweest over de vraag hoe een MSX2 de muis leest omdat de VDP van een MSX2 een hardwarematische muisleesroutine bevat, die echter niet gebruikt wordt. De twee joystickpoorten zitten op alle MSX'en aan register 14 en 15 van de PSG en de VDP heeft er geen bal mee te maken. Om een komplete leesaktie te doen is nogal wat nodig omdat de muis maar de beschikking heeft over een 4 bits databus. Om dus 2 keer een 8 bits offset te lezen (X en Y) moet er dus 4 keer gelezen worden waarbij de muis eerst verteld moet worden dat er gelezen gaat worden. Aan de hand van de routine (GTMOUS) zal ik nu het algoritme verklaren. We nemen even aan dat de muis in poort 1 zit. In dat geval staat in (PORT) de waarde 10111111B en in (PORT+1) de waarde 00010000B GTMOUS: - Lees PSG register 15 - Wis bit 6, dit geeft aan dat de muis in poort 1 zit (Zet bit 6 om aan te geven dat de muis in poort 2 zit) - Zet bit 4, zodat de muis weet dat nu XH klaargezet moet worden. Bit 5 doet hetzelfde voor poort 2 Opm: XH/YH = Bit 4-7 van X/Y offset XL/YL = Bit 0-3 van X/Y offset - Wacht even op muis (het is een relatief traag ding) - Lees XH (Verdere details volgen) - Lees XL - Lees YH - Lees YL Dit lezen is niet eenvoudig omdat de muis niet automatisch weet wanneer n van de waarden gelezen is. Om aan de muis te vertellen dat je de waarde gelezen hebt, moet bit 4 (indien de muis in poort 2 zit bit 5) van PSG register 15 ge nverteerd worden. Als tijdens de volgende leesaktie register 15 weer geschreven wordt zal de muis dit ge nverteerde bit zien waarop het beestje de volgende te lezen waarde op zijn 4 bits databus zet. Na een kleine wachttijd wordt deze waarde dan uit register 14 gelezen. EEN MUISBESTURINGSPROGRAMMA Laat ik beginnen met het bedanken van Stefan Boer die het basisprogramma voor de muisbesturing heeft gemaakt waar ik op voortgeborduurd heb. De routine is vrij universeel en werkt gegarandeerd op alle MSX'en (vanaf MSX2). Als uitvoer zal een sprite op het scherm getekend worden die de beweging van de muis volgt. Wat meteen opvalt is dat het programma nogal groot is geworden, maar dat komt omdat er maar heel weinig BIOS calls gebruikt worden. De muisroutine van de MSX2 en turbo R staat nl. in een subslot en dat maakt de routine relatief traag. Voor de meeste routines is dit niet zo'n bezwaar, maar als een routine vaak aangeroepen wordt is het toch wel handig dat alles zo vlot mogelijk verloopt. Verder bevat het programma een schat aan andere nuttige informatie. Wat dacht je bv. van de vuurknop uitleesroutine die feitelijk een kopie is van de routine die in de interruptafhandelingsroutine van FD9FH staat. Deze routine kijkt naar alle vuurknoppen (0 t/m 5) en doet dit 5 keer zo snel als de BIOS routine omdat je die in dit geval 5 keer aan zou moeten roepen. In principe is deze routine overbodig omdat er in het systeem RAM ook een byte is waar de huidige vuurknop status in staat, maar ik heb hem er toch bij gezet omdat er onder MSX programmeurs de trend bestaat om het hele systeem plat te leggen zodat er geen processortijd verloren gaat aan -voor hen- overbodige dingen en in dat geval wordt dit byte niet meer gezet. Verder bevat het programma een routine die voor SCREEN 5, page 0 twee sprites initialiseert en alle andere sprites weg definieert. Je merkt het al, dit programma bevat meer dan alleen maar een simpele muisbesturing. HOE WERKT HET Als het programma opgestart wordt zullen eerst de benodigde sprites ge nitialiseerd worden. Daarna zal naar een muis gezocht worden (CHKPRT) die in de variabele (PORT & PORT+1) aangeeft of en in welke poort de muis zich bevindt. Is geen muis aangesloten dan zal de waarde 0 in (PORT) staan. Nu wordt nog een interruptroutine ge nstalleerd die bij elke interrupt de sprites zal herplaatsen. Verder zal de routine ook altijd met de cursorkeys werken (logisch nietwaar??). Het uiteindelijke resultaat is dus een hele snelle routine die zelf wel uitzoekt of en waar een muis is aangesloten en die zowel met muis als met de cursorkeys tegelijkertijd een 'arrow' over het scherm kan bewegen in een van tevoren opgegeven venster. Een ander leuk detail is dat de muisroutine op zich ook op MSX1 werkt, maar dat dan wel de muisplaats en initialiseer routines herschreven moeten worden. Voor meer informatie over het hoe en wat van sprites moet ik jullie naar n van mijn eerdere artikelen verwijzen die op de GENIC ClubGuide Special #2 staat. Het programma staat los op deze disk (hoop ik) en heet MOUSE.ASC Als u niet zo'n ster bent in het bedienen van een assembler kunt u ook gewoon het programma MOUSE.BIN opstarten. Ik hoop dat ik wat duidelijkheid heb gebracht in de wereld van MSX muizen en natuurlijk wil ik in de toekomst een stormvloed van programma's zien die de muis gebruiken, dat spreekt voor zich (ik bedoel dus dat ik hoop dat dit muisje nog een staartje krijgt). Alex van der Wal ; Een UITERST snelle muisbesturing. ; Gepubliceerd op de Sunrise Magazine Special #1 ; Geschreven: 25 april 1992 door Alex van der Wal ; Copyright: Copyright ?? (<= variatie op Smith & Jones grap) ; VDPBF1: EQU &HF3DF ; MSX1 RAM VDP registerbuffer-0 (0 t/m 7) VDPBF2: EQU &HFFDF ; MSX2 RAM VDP registerbuffer-8 (8 t/m 23) PSGWRT: EQU &H93 PSGRD: EQU &H96 GTSTCK: EQU &HD5 GTTRIG: EQU &HD8 SPRPOS: EQU &H7600 ; Start spritepositie tabel PAGE: EQU 0 ; Eerste 64kB van VRAM MSESPD: EQU 15 ; >, dan tragere beweging van cursor CURSPD: EQU 15 ; idem, maar nu zonder muis aangesloten WACHT1: EQU 7 ; Wachtvariabele (Copyright Steve Soft) WACHT2: EQU 40 ; Idem MIN_X: EQU 10 ; 4 keer raden ! MAX_X: EQU 255-10 MIN_Y: EQU 10 MAX_Y: EQU 211-10 ORG &HB000 RUN: LD A,5 CALL &H5F ; SCREEN 5 CALL INICUR MAIN: CALL MOVCUR JR Z,MAIN ; Geen knop ingedrukt PUSH BC CALL STPCUR XOR A CALL &H5F POP AF ; In A staat nu de ingedrukte knop RET INICUR: DI LD A,15 ; Init sprites op page 0, screen 5 OUT (&H99),A LD (VDPBF1+6),A LD A,128+6 OUT (&H99),A ; Zet startadres van patroontabel LD A,239 OUT (&H99),A LD (VDPBF1+5),A ; referentieadres waaruit het startadres LD A,128+5 ; van zowel de positietabel als de OUT (&H99),A ; kleurtabel gehaald kan worden. LD A,0 OUT (&H99),A LD (VDPBF2+11),A LD A,128+11 OUT (&H99),A ; idem (Reg 5 en Reg 11 vormen samen 1 adres) LD HL,&H7800 ; Patroontabel startadres LD C,0 CALL NSTWRT EI LD HL,SPRDAT LD BC,&H4098 OTIR ; Stuur spritedata uit LD HL,&H7600 ; Positietabel startadres LD C,0 DI CALL NSTWRT EI LD B,32 ; 4 bytes per sprite en 32 sprites INC_L1: LD A,216 OUT (&H98),A ; Y XOR A OUT (&H98),A ; X XOR A OUT (&H98),A ; Spritenummer XOR A OUT (&H98),A ; Gereserveerd DJNZ INC_L1 LD HL,&H7400 ; Kleurtabel LD C,0 DI CALL NSTWRT EI LD A,1 LD B,16 INC_L2: OUT (&H98),A ; Kleur sprite 0 is 1 (zwart) DJNZ INC_L2 LD A,15 ; Kleur sprite 1 is 15 (wit) LD B,16 INC_L3: OUT (&H98),A DJNZ INC_L3 LD BC,&H98 ; Wis rest buffer, om rotzooi sprites te LD DE,30*16 ; voorkomen INC_L4: OUT (C),B DEC DE LD A,D OR E JR NZ,INC_L4 LD A,(VDPBF1+1) RES 0,A ; Magnitude is klein SET 1,A ; Grootte is 16x16 DI OUT (&H99),A LD (VDPBF1+1),A LD A,128+1 OUT (&H99),A ; Sprite Size = 16*16, magnify = off LD A,(VDPBF2+8) RES 1,A OUT (&H99),A LD (VDPBF2+8),A LD A,128+8 OUT (&H99),A ; Zet sprites aan EI LD A,120 ; Start X en Y waarden LD (X_COOR),A LD A,96 LD (Y_COOR),A CALL CHKPRT ; Zoek en installeer muis CALL INIMOV ; Zet int. hooks LD A,CURSPD LD (CUR_V1),A LD (CUR_V2),A LD A,(PORT) AND A RET Z LD A,MSESPD LD (CUR_V1),A LD (CUR_V2),A RET INIMOV: DI LD HL,&HFD9F LD DE,OLDHOK LD BC,5 LDIR LD A,&HC3 ; Interrupt voor cursor naar scherm rout. LD (&HFD9F),A LD HL,PUTSPR LD (&HFDA0),HL EI RET STPCUR: DI LD HL,OLDHOK ; Herstel oude int. hook LD DE,&HFD9F LD BC,5 LDIR LD A,(VDPBF2+8) SET 1,A OUT (&H99),A LD (VDPBF2+8),A LD A,128+8 OUT (&H99),A ; Zet de sprites uit EI RET CHKPRT: LD A,&B10111111 LD (PORT),A LD A,&B00010000 LD (PORT+1),A CALL CHP_P1 RET NZ ; Muis in poort 1 aanwezig EI HALT HALT LD A,&B11111111 LD (PORT),A LD A,&B00100000 LD (PORT+1),A CALL CHP_P1 RET NZ ; Muis in poort 2 aanwezig XOR A LD (PORT),A ; Geen muis aangesloten RET CHP_P1: CALL GTMOUS ; Test of cursor langzaam naar de EI ; rechteronderhoek beweegt. Is dit zo HALT ; dan is er geen muis in de te testen HALT ; poort aangesloten. CALL GTMOUS LD A,H CP 255 RET NZ LD A,L CP 255 RET MOVCUR: CALL MOUSE ; Lees muis (indien aanwezig) CALL CURSOR ; Lees cursor CALL FIRE ; Lees vuurknoppen RET ; Z_flag hoog, dan geen knop ingedrukt MOUSE: LD A,(PORT) AND A RET Z ; Geen muis aangesloten LD A,(MSE_V2) AND A RET Z XOR A LD (MSE_V2),A ; Er is een interrupt geweest CALL GTMOUS LD C,L LD A,H ; X_offset NEG ; Naar rechts, dan X_offset is negatief LD HL,X_COOR ; met NEG wordt deze pos. gemaakt CALL XBORDR LD (HL),A ; X_coordinaat INC HL LD A,C ; Y_offset NEG CALL YBORDR LD (HL),A ; Y_coordinaat RET GTMOUS: LD A,15 CALL PSGRD ; Lees PSG reg. 15 LD IX,PORT AND (IX+0) ; Geef opdracht tot muis leesaktie OR (IX+1) LD E,A LD B,WACHT2 CALL GTOFS2 ; Lees bit 7-4 van X-offset RLCA RLCA RLCA RLCA LD C,A CALL GTOFST ; Lees bit 3-0 van X-offset OR C LD H,A ; Sla komplete offset in H op CALL GTOFST ; Lees bit 7-4 van Y-offset RLCA RLCA RLCA RLCA LD C,A CALL GTOFST ; Lees bit 3-0 van Y-offset OR C LD L,A ; Sla komplete offset in L op RET GTOFST: LD B,WACHT1 GTOFS2: LD A,15 CALL PSGWRT ; Schrijf E naar PSG reg. 15 LD A,(IX+1) XOR E ; Geef door dat volgend nibble verstuurd LD E,A ; moet worden. WACHT: DJNZ WACHT ; Wacht tot informatie aanwezig is LD A,14 CALL PSGRD ; Lees PSG reg. 14 AND &H0F ; Alleen bits 3-0 zijn geldig RET XBORDR: BIT 7,A ; Zorg dat cursor binnen gedefinieerde JR Z,XBO_S1 ; border blijft voor de X beweging NEG LD B,A LD A,(HL) SUB B JR C,XBO_S2 CP MIN_X RET NC XBO_S2: LD A,MIN_X RET XBO_S1: ADD A,(HL) JR C,XBO_S3 CP MAX_X RET C XBO_S3: LD A,MAX_X RET YBORDR: BIT 7,A ; Idem als XBORDR, maar nu voor de JP Z,YBO_S1 ; Y beweging NEG LD B,A LD A,(HL) SUB B JR C,YBO_S2 CP MIN_Y RET NC YBO_S2: LD A,MIN_Y RET YBO_S1: ADD A,(HL) CP MAX_Y RET C LD A,MAX_Y RET ; Cursor besturing ; CURSOR: CALL CURDLY ; Cursor vertraging RET NZ XOR A CALL GTSTCK ; A=STICK(0) EI RLCA LD E,A LD D,0 LD HL,CURBUF ; Cursor bewegingsbuffer ADD HL,DE LD A,(HL) ; Y beweging LD B,A PUSH BC INC HL LD A,(HL) ; X beweging LD HL,X_COOR CALL XBORDR LD (HL),A ; X coordinaat INC HL POP AF CALL YBORDR LD (HL),A ; Y coordinaat RET CURDLY: LD A,(CUR_V1) ; Vertraag de cursor DEC A ; Omdat hij anders VEEL te snel zou LD (CUR_V1),A ; gaan. RET NZ LD A,(CUR_V2) LD (CUR_V1),A RET FIRE: XOR A CALL FIR_P1 AND &H30 ; Poort 1 op bit 4+5 PUSH AF LD A,1 CALL FIR_P1 AND &H30 RRCA RRCA ; Poort 2 op bit 3+4 POP BC OR B PUSH AF CALL FIR_P2 AND 1 RRCA RRCA ; Spatie op bit 6 POP BC OR B RRCA RRCA CPL LD B,1 BIT 4,A RET NZ INC B BIT 2,A RET NZ INC B BIT 0,A RET NZ INC B BIT 3,A RET NZ INC B BIT 1,A RET FIR_P1: LD B,A LD A,15 DI CALL PSGRD DJNZ FIR_S1 AND &HDF OR &H4C JR FIR_S2 FIR_S1: AND &HAF OR 3 FIR_S2: OUT (&HA1),A LD A,14 CALL PSGRD EI RET FIR_P2: DI IN A,(&HAA) AND &HF0 ADD A,8 OUT (&HAA),A IN A,(&HA9) EI RET PUTSPR: LD A,2 ; Indien de VDP al met een aktie bezig CALL QRSTAT ; is wordt er niets met de VDP gedaan RRCA JR C,OLDHOK DI LD HL,SPRPOS LD C,PAGE CALL NSTWRT LD A,(Y_COOR) LD B,A OUT (&H98),A ; Y LD A,(X_COOR) LD C,A OUT (&H98),A ; X XOR A OUT (&H98),A ; Sprite nummer XOR A OUT (&H98),A LD A,B OUT (&H98),A ; Y LD A,C OUT (&H98),A ; X LD A,4 OUT (&H98),A ; Sprite nummer LD (MSE_V2),A ; Zorg voor timing muisroutine OLDHOK: DS 5 ; Hier komt de oude hook te staan QRSTAT: DI ; Lees een VDP statusregister OUT (&H99),A LD A,128+15 ; Zet het te lezen statusregister OUT (&H99),A ; VDP register 15 NOP NOP ; Vertraging die VDP nodig heeft IN A,(&H99) ; Lees statusregister EX AF,AF XOR A OUT (&H99),A LD A,128+15 ; zet register 15 weer op 0 (Dit MOET !!) OUT (&H99),A EX AF,AF EI RET NSTWRT: LD A,H ; Zet het 'direct VRAM write adress' AND &H3F ; Het adres staat in C & HL OR &H40 ; C bevat alleen bit 16 van het adres EX AF,AF ; en HL bevat bits 0 t/m 15 LD A,H AND &HC0 OR C RLCA RLCA OUT (&H99),A LD A,128+14 OUT (&H99),A LD A,L OUT (&H99),A EX AF,AF OUT (&H99),A RET ; ; ** Data ; X_COOR: DB 128 ; X coor. van cursor/muis Y_COOR: DB 106 ; Raad eens ! PORT: DB 0 ; Poort waar muis in zit DB 0 CUR_V1: DB 0 ; Vertragingsvariabele CUR_V2: DB 0 ; idem. MSE_V2: DB 0 ; interrupt vlag CURBUF: DB 0,0,255,0,255,1,0,1,1,1,1,0,1,255,0,255,255,255 ; Patroondata van de twee sprites SPRDAT: DB &HC0,&HA0,&H90,&H88,&H84,&H82,&H81,&H87 DB &H84,&HA2,&HE2,&H91,&H11,&H08,&H08,&H07 DB &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00 DB &H00,&H00,&H00,&H00,&H00,&H80,&H80,&H00 DB &H00,&H40,&H60,&H70,&H78,&H7C,&H7E,&H78 DB &H78,&H5C,&H1C,&H0E,&H0E,&H07,&H07,&H00 DB &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00 DB &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00 END