Call cartridge Genic Clubguide, 00-00-00 MACHINETAAL: C A L L C A R T R I D G E ============================= De nu volgende tekst is ook te vinden op de BBS-waterland en is geschreven door Ramon van der Winkel die GENIC toe- stemming heeft gegeven voor deze publicatie. Aan de publicatie van dit artikel hebben meegewerkt: Ramon van der Winkel (De schrijver van het artikel) Rudy Oppers (De man van de modem) Alex van der Wal (Initiatiefnemer & editor) Deze tekstfile legt uit hoe een software-cartridge gemaakt kan worden, die met CALL aan te roepen is. De software zal in Z80-machinetaal geschreven moeten worden, het kunnen programmeren in deze taal is dus een voorwaarde. Verder is enige kennis van de slot structuur van de MSX van belang (pagina's, sloten etc). Als de computer opgestart of gereset wordt, wordt als eerste de MSX-BIOS-ROM aangeroepen. Deze zal het hele geheugen opzetten, zodat er BASIC programma's gerunt kunnen gaan worden. Als een van de laatste acties kijkt de BIOS-ROM of er in een van de sloten een externe-ROM zit. Deze is voor de BIOS-ROM herkenbaar, omdat de eerste twee bytes van de externe rom een 65 en een 66 zijn, de ascii codes voor een A en een B. Komt de BIOS-ROM deze codes tegen, dan wordt er een tabel achter die twee codes verwacht, die op de volgende manier is opgebouwd: +0 "A" +1 "B" +2 INITIALISE Address LSB +3 INITIALISE Address MSB +4 STATEMENT Address LSB +5 STATEMENT Address MSB +6 DEVICE Address LSB +7 DEVICE Address MSB +8 BASIC TEXT Address LSB +9 BASIC TEXT Address MSB +A\ . \ . +- Gereserveerd, meestal 0 . / +F/ Voor ons zijn voorlopig alleen de adressen +0 tot en met +5 van belang, de andere adressen worden gebruikt voor de uit- breiding van de DEVICES (COM:, CAS:, A:, etc) en de BASIC (een BASIC programma in de ROM). Het startadres van deze cartridge is 4000h of 8000h, voor adres 0000 zijn andere afspraken, adres C000h is niet te gebruiken, omdat de rom daar zijn systeem variabelen heeft staan en we die pagina dus niet weg kunnen schakelen. De diskrom bijvoorbeeld staat vanaf adres 4000h, laten we er voor het gemak maar even vanuit gaan, dat wij ons programma daar ook neer gaan zetten. De ROM was dus aan het opstarten, en vond de cartridge indentificatiecodes A en B. Nu gaat de ROM het adres van +2 en +3 ophalen, en springt daar, als het niet 0000 is, naar toe. Dit adres wordt dus na de reset van de computer een- malig aangeroepen. Ons programma kan daar dus een stukje van zichzelf initialiseren in het geheugen (als dat mogelijk mocht zijn). De diskrom, om daar maar weer eens naar toe te gaan, zet hier de koppen van de drives in de uitgangspositie en initialiseert een aantal buffers en systeem variabelen van adres 0F37Fh en lager (naar C200H toe dus). Daarna kijkt de ROM naar de andere adressen. Als op +4 en +5 een adres staat, dan wordt in een special tabel gesigneerd dat ons programma een CALL uitbreiding ondersteund. Zo wordt ook voor de DEVICE en de BASIC TEXT een bit gezet in die speciale tabel. De tabel staat vanaf adres 0FCC9h en is als volgt opgebouwd: Per slot worden 16 bytes bijgehouden, per secundair slot binnen dat slot 4 bytes (4 secundair slot keer 4 bytes = 16 bytes). Per secundair slot wordt weer per pagina een byte bijgehouden (4 pagina's keer 1 byte = 4 bytes). Willen we dus de informatie over de pagina van de diskrom en zit deze in pagina 1 (4000h..7FFFh) in slot 3-2, dan bepalen we het adres in de tabel met de volgende formule: 0FCC9h + Primair slot nummer * 16 + secundair slot nummer *4 + pagina nummer Hier is dat dus 0FCC9h+3*16+2*4+1 = 0FCC9h+57 = 0FD02h. Hier staat dus een byte met de speciale informatie omtrend de diskrom. De byte is weer als volgt opgebouwd: Bit7 = 1: BASIC TEXT handler gevonden Bit6 = 1: DEVICE handler gevonden. Bit5 = 1: CALL handler gevonden. Op het moment dat er dus een CALL <tekst> uitgevoerd wordt, worden alle pagina's in de sloten, waarvan Bit5 geSET is, aangeroepen. Hoe de software dan weer in elkaar moet zitten, leg ik nu uit. Stel, op adres 4000h+4 en +5 staat de waarde 4010h, dan begint ons programma dus vanaf adres 4010h. Op het moment dat onze routine door de rom wordt aange- roepen, staat vanaf adres 0FD89h de <tekst> die achter het CALL statement was opgegeven. Alleen het eerste woord staat hier dus. De <tekst> wordt door een 0 afgesloten, is maximaal 15 tekens lang en is al helemaal omgezet in hoofd- letters. Tekens als een komma zijn er al tussenuit ge- filterd. (Probeer het maar eens: CALL S,Y,S,T,E,M dit werkt!). Verder bevat register HL de pointer naar de rest van de tekstregel, vervolgt achter de <tekst> van de call. Als we bijvoorbeeld CALL TEST ("Ramon",0) willen doorgeven, dan staat de tekst TEST vanaf adres 0FD89h, gevolgt door een 0 en staat register HL op de spatie achter de tekst TEST. Als we de tekst op adres 0FD89h getest hebben en hij komt overeen met wat wij ervan dachten (TEST dus), dan roepen we onze eigen routines aan, die de rest afhandelen. LET WEL OP: Geen registers veranderen, zeker HL niet. Als we daarna terugkeren, zorgen we ervoor, dat we de Carry flag geRESET hebben. Op die manier weet de ROM, dat de tekst door ons behandeld is en dat er niet verder geprobeert hoeft te worden, door de diskrom bijvoorbeeld. Bevalt de tekst ons echter niet, er is bijvoorbeeld TETS ingetypt, dan zetten we de Carry flag en we keren weer terug. De rom ziet dan dat de Carry flag gezet is en hij zal het in de andere pagina's met een call-handler bit in de speciale tabel gezet, gaan proberen. Als er geen pagina's meer zijn, wordt er de foutmelding 'Syntax error' gegeven. Houdt verder in de gaten dat de stack door de eigen routines niet verknald wordt. Van te voren even opslaan en dan in de eigen (RAM) pagina zetten, zorgt voor een veilige terugkeer. Nu zitten we nog met een probleem: Als wij een eigen stukje software hebben geladen vanaf adres 4000h, met de cartridge header erboven, hoe vertellen we dan aan de ROM, dat wij een call-handler ondersteunen, zonder dat we de computer hoeven te resetten, om de rom het zelf te laten ondervinden? Heel eenvoudig. We bepalen ons eigen slot-id (het primair en secundaire slot waar we inzitten) en we berekenen de positie van de onze pagina in de speciale tabel en we zetten daar Bit5, de rom weet dan dat wij een call-handler ondersteunen. Ik laat het hier voorlopig even bij, hieronder staan nog een paar handige routines en een voorbeeld van een kant en klaar programma met een cartridge header en een installatie programma dat Bit5 zet. Op de DEVICE en BASIC TEXT handler wil ik niet verder in- gaan, omdat het dan nog moeilijker wordt en de meeste mensen hier al moeite genoeg mee zullen hebben. Veel sucses !! Ramon van der Winkel Wouter Sluislaan 12 1461 AC Zuidoostbeemster Via BBS Waterland (02990-40202/45740): Post aan RAMON VAN DER WINKEL, bord MSX. De voorbeeld programma's: ORG 04000H ; CARTHEAD DEFB "AB" DEFW 0 ;Geen INITIALISE handler DEFW CALHAN ;CALL handler DEFS $4010-$ ;De rest vullen met 00 ; CALHAN PUSH HL ;Store tekstpointer LD DE,_STATEM ;Onze tekst LD HL,0FD89H ;De <tekst> CALHAN_LUS LD A,(DE) ;Ons teken CP (HL) ;Vergelijk JR NZ,CALHAN_BAD ;Niet hetzelfde, return met INC HL ;met Carry set INC DE AND A ;Einde (00) ? JR NZ,CALHAN_LUS ;Nog niet bereikt CALL ENTRY ;Onze eigen routine aanroepen SUB A ;Reset carry JR CALHAN_EXIT ; CALHAN_BAD SCF ;Tekst niet herkend CALHAN_EXIT POP HL ;Restore tekstpointer RET ; _STATEM DEFB "TEST",0 ; ENTRY ;Hier komt je eigen routine te staan RET ; Opm: Er kunnen natuurlijk ook meerdere vergelijkingen gedaan worden, op meerdere teksten, het hoeft niet bij maar een vergelijking te blijven! (vergelijk diskrom: CALL SYSTEM en CALL FORMAT). De routine om het callhandler bit in de special tabel te setten. SETCALLBIT CALL GETOWNID ;Je eigen slotID ophalen PUSH AF AND %00000011 ;Primaire slot SLA A ;*2 SLA A ;*4 SLA A ;*8 SLA A ;*16 LD C,A POP AF AND %00001100 ;Secundair slot (al *4) OR C INC A ;Pagina 1 LD C,A LD B,0 LD HL,0FCC9H ;Speciale tabel ADD HL,BC ;+ Offset SET 5,(HL) ;Call handler bit RET ; GETOWNID DI IN A,(0A8H) SRL A SRL A AND 3 ;Primaire slot van LD C,A ;onze pagina LD B,0 LD HL,0FCC1H ADD HL,BC ;Naar de 'expanded' tabel OR (HL) ;Bit7=0 -> Geen sec slots RET P ;Niet dus LD C,A INC HL INC HL ;Ga nu naar de tabel met de INC HL ;actieve secundaire slot INC HL ;setting van iedere pagina LD A,(HL) AND %00001100 ;Van pagina 1 OR C ;En het primaire slot erbij RET ; |