CoBra - Software de BOOT

Această pagină prezintă cîteva aspecte legate de software-ul de BOOT folosit pe calculatorul CoBra. Este vorba de programul scris în ROM-ul de BOOT, care se lansează imediat la pornirea calculatorului în configuraţia hardware de start. În mod tradiţional, ca BOOT ROM pentru CoBra pe vremea respectivă se folosea cîte un EPROM cu capacitate de 2KB. Totuşi CoBra poate accesa un BOOT ROM cu capacitatea de maxim 16KB, şi după cum veţi vedea în continuare eu m-am folosit cu succes de acest prerogativ.

BOOT ROM-uri folosite cu CoBra



Pentru fiecare BOOT ROM de mai jos, sînt disponibile două link-uri: unul cu listingul dezasamblării codului de BOOT ROM, un click pe el va deschide pagina cu listingul, şi un link pentru descărcarea imaginii binare ROM respective

Pentru configuraţia cu 64K RAM

Pentru configuraţia cu 80K RAM

BOOT standard (v.1)

Imagine ROM (Right-click, Save As)
Aceasta e versiunea recuperată dintr-un EPROM păstrat de mine de pe vremea respectivă (1990-1992). L-am folosit iniţial, cînd am pornit prima placă de bază în configuraţia cu 64K RAM. Codul este identic cu fişierul "boot64k_v2.bin" din arhiva "Cobra_BOOT_roms.zip" postată pe forum de către mihaila_ac. BOOT standard (v.1)

Imagine ROM (Right-click, Save As)
Aceasta e versiunea recuperată din EPROM-ul de pe plăcile de bază construite de mine pe vremea respectivă (1990-1992). L-am folosit pe ambele plăci de bază după ce le-am modificat pentru 80K RAM. Această versiune este aproape identică cu cea din fişierul "boot80k_v3.bin" din arhiva "Cobra_BOOT_roms.zip" postată pe forum de către mihaila_ac.
BOOT de test standard

Imagine ROM (Right-click, Save As)
Codul de BOOT de test standard pentru CoBra. Acest cod a fost iniţial scris pentru configuraţia cu 64K RAM. Eu l-am modificat în aşa fel încît să poată fi rulat în ambele configuraţii.
BOOT de test HOMOK

Imagine ROM (Right-click, Save As)
Un cod de BOOT provenit de la un prieten, cu teste hardware pentru CoBra în configuraţie de 64K RAM BOOT "Mastery Electronics"

Imagine ROM (Right-click, Save As)
Un cod de BOOT provenit de la un prieten, în esenţă este codul standard de BOOT 80K dar cu o grafică total diferită

CoBra Boot Manager

Afară de aceste versiuni de BOOT, eu personal am scris un cod pe care l-am denumit Boot Manager şi care este lansat în loc de codul de BOOT obişnuit, de la adresa 0000h. La pornire este afişat un meniu din care se selectează unul din codurile de BOOT prezentate în tabelul de mai sus. Ideea mea a fost să fac cumva să pot alege la pornire unul din aceste coduri de BOOT, fără să fie nevoie să schimb ROM-ul din soclul de pe placa de bază. Scopul este unul mai degrabă istoric, acela de a face cumva să păstrez aceste coduri de BOOT diferite, scrise de diverse persoane pentru CoBra, ca într-un muzeu de BOOT-uri, dacă se poate spune aşa.

Prezint mai jos sursa programului, care poate fi descărcată, la fel ca şi codul binar rezultat prin asamblare (MasterBoot-CoBra+CPM_rev.01.bin) cu un righ-click pe cele două link-uri din capul tabelului.

CoBra Boot Manager - sursa în Assembler

(MasterBoot-CoBra+CPM_rev.01.asm) (MasterBoot-CoBra+CPM_rev.01.bin)

Codul de BOOT astfel rezultat, pe care l-am denumit "Boot CoBra unificat", încape în cei maxim 16 KB ai zonei de cod BOOT pe care CoBra îi poate adresa la pornire.

Conţine Boot Manager-ul cu mărimea de 2KB de la adresa 0000h, şi imediat după, codurile de BOOT enumerate în tabelul de mai sus, dar modificate de mine în aşa fel încît să poată rula relocate la o adresă diferită de 0000h.

Harta memoriei ocupate de aceste componente în "Boot-ul CoBra unificat" - aşa cum ales eu să le plasez, este următoarea: (codul binar asamblat pentru întregul BOOT ROM de 16 KB poate fi descărcat cu un right-click pe link-ul din dreapta)

Harta memoriei pentru "Boot-ul CoBra Unificat"

Spaţiu liber$3000-$3FFF Fişierul 16K_UNIFIED_BOOT_rev.01.bin pe care-l puteţi descărca aici ($3000 = 12288 octeți, întrucît $1000 octeți rămîn neprogramați) conţine imaginea unui BOOT ROM de 16KB pentru CoBra, pe care-l puteţi scrie într-un EPROM şi folosi într-un calculator CoBra, indiferent că are configuraţie hardware de 64KB sau 80KB. Recomand folosirea lui în conjuncţie cu imaginea SYSTEM ROM de 64 KB descărcabilă mai jos, care conţine şi un sistem CP/M rulabil direct din ROM (numai în configurația cu 80 KB RAM), cu una din 4 combinaţii de taste posibile (vezi tastele descrise mai jos).
BOOT "Mastery Electronics" 80K RAM$2800-$2FFF
BOOT de test standard 64K / 80K RAM$2000-$27FF
BOOT de test HOMOK 64K RAM$1800-$1FFF
BOOT standard (v.1) 80K RAM$1000-$17FF
BOOT standard (v.1) 64K RAM$0800-$0FFF
CoBra Boot Manager$0000-$07FF

Harta memoriei pentru SYSTEM ROM utilizabil cu "Boot-ul CoBra Unificat"

Spaţiu liber$F34B-$FFFF Fişierul SYSTEM_ROM.bin pe care-l puteţi descărca aici ($F34B = 62283 octeți, întrucît $0CB5 = 3253 octeți rămîn neprogramați) conţine imaginea unui SYSTEM ROM de 64KB pentru CoBra, pe care-l puteţi scrie într-un EPROM şi folosi într-un calculator CoBra, în conjuncţie cu imaginea de "Boot CoBra Unificat" de 16KB de mai sus, care conţine cod pentru lansarea sistemului CP/M stocat în acest SYSTEM ROM (numai în configurația cu 80 KB RAM), cu una din 4 combinaţii de taste posibile (vezi tastele descrise mai jos).

Codul rutinei NMI$F20E-$F34A
15 octeți nefolosiți ($00)$F200-$F20E
CPM 80 coloane text$C000-$F1FF
DEVIL$8000-$BFFF
BASIC Spectrum$4000-$7FFF
OPUS v.3.2$0000h-$3FFF

Precizare importantă:

  • Pentru lansarea sistemului CP/M stocat în SYSTEM ROM-ul prezentat mai sus ESTE NECESARĂ utilizarea "Boot-ul CoBra Unificat" de mai sus,
  • Pentru lansarea sistemului CP/M stocat pe DISCHETĂ, trebuie lansat (din meniul "Boot-ului CoBra Unificat") unul din codurile BOOT ROM vechi, și din acest cod BOOT original, cu tasta D se poate încărca un sistem CP/M de pe dischetă.

La pornirea calculatorului, pe ecran va fi afişată una din cele două imagini de mai jos, în funcţie de configuraţia hardware:
Pentru CoBra 64K va fi afişată imaginea din stînga, iar pentru CoBra 80K imaginea din dreapta.

Boot Manager cu CoBra 64K RAM

Boot Manager cu CoBra 80K RAM

Imaginea de start afişată de Boot Manager pentru configuraţia de 64K RAM.

Cu săgeţile SUS/JOS se poate selecta unul din cele 3 coduri de BOOT disponibile din meniul din stînga, apoi cu ENTER se lansează acel cod.
Imaginea de start afişată de Boot Manager pentru configuraţia de 80K RAM.

Cu săgeţile SUS/JOS se poate selecta unul din cele 3 coduri de BOOT disponibile din meniul din dreapta, apoi cu ENTER se lansează acel cod.

Asta înseamnă că acest cod face autodetecţia configuraţiei hardware a respectivului calculator. Meniul activ din care se poate alege unul din codurile de BOOT propriu-zise va fi stabilit în funcţie de configuraţie: pentru CoBra 64K va fi activ meniul din stînga iar pentru CoBra 80K cel din dreapta.

De asemenea sînt active şi următoarele taste: NOTĂ:

1. La lansarea CP/M din ROM, sistemul va solicita prezenţa unei dischete în unitatea implicită pe care o alegeţi. Nu e nevoie ca discheta să fie dischetă sistem şi nici să conţină vreun fişier, dar trebuie cel puţin să fie formatată. Puteţi folosi foarte bine un emulator fizic de unitate floppy, cu o imagine de dischetă CP/M CoBra de 720K, care emulator să emuleze o unitate fizică conectată ca unitate 0, 1, 2 sau 3 (codul ales la lansarea cu CTRL+n descrisă mai sus).

2. Tasta 4 enumerată mai sus nu va funcţiona corect cu imaginea SYSTEM_ROM.bin postată aici, deoarece aceasta conţine în sfertul superior (C000-FFFF) imaginea CP/M rulabilă din ROM, care evident trebuie lansată în configuraţie CP/M, nu în configuraţie BASIC. Atunci cînd am scris codul Boot Manager, l-am scris pentru cazul general al unui SYSTEM ROM de 64KB conţinînd 4 sisteme de gen BASIC a 16K fiecare. Ulterior am venit cu "trăznaia" de CP/M lansabil din ROM, pe care l-am pus în sfertul superior al SYSTEM ROM în locul unui BASIC cu NMI.

3. Tasta N - pentru încărcare Basic cu NMI - va încărca în RAM BASIC-ul standard care se încarcă în cazul apăsării tastei B, în care apoi se va insera un cod scris de mine pentru o rutină de NMI. Detalii despre folosirea acestei rutine sînt prezentate la secţiunea "Software" "BASIC + NMI".

Problemele de care m-am lovit în scrierea Boot Manager-ului au fost două:
  1. Scrierea unui cod care să funcţioneze pe post de BOOT în CoBra
  2. Modificarea codurilor de BOOT originale enumerate în tabel în aşa fel încît să poată rula relocate la adrese diferite de 0000 de unde rulează în mod normal

1. Scrierea unui cod care să funcţioneze pe post de BOOT în CoBra



    1. Principala problemă la scrierea unui cod de BOOT pentru acest calculator este modul în care se face ieşirea circuitului de interfaţă 8255 din starea de RESET. Este vorba de faptul că 8255 foloseşte un semnal de RESET activ pe "1" logic, pe cînd microprocesorul (Z80) foloseşte un semnal de RESET activ pe "0". Pentru înţelegerea fenomenului trebuie examinat Circuitul de configurare şi selecţie. După cum şi manualul hardware o spune, dioda D02 asigură ieşirea microprocesorului din starea de RESET cu cîteva milisecunde mai devreme decît dezactivarea semnalului NPOR (care e activ pe "0"). Semnalul NRST folosit pentru Z80 pleacă de pe anodul diodei D02, iar semnalul NPOR se află pe catodul ei. Iar semnalul NPOR generează prin inversare cu poarta U17/8,9,10 semnalul POR care e dus la intrarea RST a 8255. Deci practic Z80 iese din starea de RESET binişor mai devreme decit 8255. Ori asta poate cauza probleme la pornire pentru că 8255 este folosit la generarea unor semnale care determină configuraţia calculatorului, mai exact O5 şi mai ales O6, fiind practic nevoie de o rutină la începutul programului de BOOT care să furnizeze o oarecare întîrziere înainte de a se încerca configurarea lui 8255. 8255 poate funcţiona în multe configuraţii, dar la CoBra este folosit numai într-una singură: Porturile A şi B ca porturi de intrare, iar portul C ca port de ieşire. Configurarea lui se face cu o secvenţă de instrucţiuni OUT, iar acestea trebuie executate cu o mică întîrziere după pornirea calculatorului, pentru a da suficient timp lui 8255 sa iasă din RESET, altfel instrucţiunile nu vor avea nici un efect.

    2. Un alt aspect legat de scrierea unui cod de BOOT este acela al programelor (de regulă jocuri, dar nu numai) concepute să ruleze în Spectrum BASIC, stocate pe dischete flexibile CP/M si lansate din CP/M. La prima vedere probabil că aceste două lucruri par să nu aibă nici o legatură, dar...

Ce se întîmplă la lansarea unui astfel de program? Se lansează un executabil cu extensia .COM din CP/M, care conţine codul programului propriu zis, precedat de o mică bucată de cod popular denumită pe vremea respectivă "Loader". Întrucît Loader-ul se află la începutul executabilului, el se va executa primul atunci cînd este lansat fişierul .COM. Ceea ce trebuie să se întîmple este ca Loader-ul să plaseze codul programului Spectrum în memorie la adresa corespunzătoare, să schimbe configuraţia hardware a calculatorului din configuraţie CP/M în configuraţie BASIC, şi apoi să predea controlul programului Spectrum. Pentru înţelegerea problemei, redau mai jos codul dezasamblat al Loader-ului din primul sector al unui joc Spectrum (Matchday) - ales la întîmplare dintre cele păstrate pe dischetele mele CP/M - şi un comentariu:

"CPM Game Loader.asm" este o scurtă secvenţă de cod, ocupînd o mică parte din începutul unui sector (512 octeti, din care cea mai mare parte e nefolosită, plină cu zerouri) care lansează o aplicaţie Spectrum din CP/M. Este ataşată la începutul codului aplicaţiei propriu-zise şi rezultatul este salvat pe disc ca executabil CP/M (.COM).
**********************
Acest loader este proiectat să funcţioneze în conjuncţie cu codul standard de BOOT pentru CoBra 80K (mai exact cu rutina de încărcare BASIC de la adresa 0038h din BOOT-ul de CoBra 80K). Cu alte cuvinte, dacă doriţi să scrieţi un cod de BOOT nou sau diferit pentru CoBra 80K, AVEŢI NEVOIE DE ACEASTĂ RUTINĂ PREZENTĂ LA 0038h.
**********************
Loader-ul practic încarcă codul aplicaţiei în zona de memorie standard Spectrum (4000-FFFF, adică DRAM#1-#3), după care comută calculatorul în configuraţie BASIC, încarcă BASIC-ul din ROM şi lansează aplicaţia din punctul ei de intrare.

Pentru a trece din configuraţie CP/M (PO=0, LO6=1) în configuraţie Spectrum (BASIC, PO=0, LO6=0), calculatorul trebuie mai întîi să treacă prin configuraţia de start (COBRA, PO=1, LO6=1). Explicaţia acestui fapt poate fi găsită examinînd Circuitul de configurare şi selecţie din schemele CoBra. În esenţă PO este ieşirea unui bistabil (1/2 din 7474) şi PO acţionează intrarea de clock a unui al doilea bistabil, a cărui ieşire este LO6. Din moment ce 7474 are intrări de clock active pe front pozitiv, asta înseamnă că dacă PO="0" (PO="1"), pentru ca starea celui de-al doilea bistabil să se schimbe trebuie ca PO să treaca în "1" şi apoi din nou în "0".

Codul loader-ului comută calculatorul în configuraţie de start şi se termină cu o instrucţiune RST 38h. Asta înseamnă un salt la adresa 0038h în configuraţia de start, care se află la începutul BOOT ROM.

La 0038h, codul de BOOT CoBra 80K conţine o rutină care încarcă un sistem de operare din ROM (BASIC, OPUS, DEVIL etc.) în DRAM#0 şi apoi schimbă configuraţia hardware în configuraţie Spectrum după care sare la adresa stocată în registrul HL'. Loaderul de joc din CP/M exact asta stochează în HL' înainte de a ieşi din CP/M: adresa de start a aplicaţiei Spectrum. Evident instrucţiunea respectivă (linia 0024h, LD HL,$4600) trebuie modificată în funcţie de aplicaţia Spectrum concretă pentru a conţine adresa ei de start corectă.

Daca SYSTEM ROM e mai mare decît cei 16K standard, sistemul de operare care se încarcă este selectat cu semnalul SO (Serial Out) de la 8255/pin 10, care este în mod tradiţional conectat la linia de adresă A14 de la SYSTEM ROM.

Standardul de facto pe vremea respectivă era ca Spectrum Basic să se stocheze în domeniul 4000-7FFF dintr-un ROM de 32K (deci în jumătatea lui superioară), deci semnalul SO trebuie să treacă în "1" pentru a putea încărca Spectrum Basic.

2. Modificarea codurilor de BOOT originale



Pentru modificarea codurilor originale de BOOT enumerate în tabelul anterior a trebuit mai întîi să dezasamblez fiecare cod şi să-l analizez în întregime. Apoi am marcat toate liniile conţinînd instrucţiuni de salt absolut (JP), apeluri de subrutine interne (CALL), instrucţiuni de încărcare regiştri cu valori folosite ulterior ca adrese ale unor locaţii interne codului de BOOT. Am făcut apoi o listă cu locaţiile care trebuiau modificate şi am modificat manual aceste locaţii din cadrul codului de BOOT original respectiv. Un clic pe denumirea unui cod de BOOT din tabelul anterior va afişa listingul dezasamblat al acelui cod de boot, cu comentariile mele şi cu aceste linii marcate la sfîrşit cu stringul "---@@@".