Jak się kiedyś robiło polskie litery: praktyczny przykład z roku 1991

Dokumentacja:

(Tekst pochodzi z jakiegoś zamierzchłego edytora, stąd osobliwości, mimo oczyszczenia…)

*═══════════════════════════════════════════════════════*
EMUlator
Polskojęzyczne Środowisko programów.

*═══════════════════════════════════════════════════════*
CO TO JEST.

Program EMU (EMUlator bios’a) tworzy zintegrowane polskojęzyczne środowisko dla programów , korzystających przy obsłudze ekranu z funkcji BIOSa, głównie Clippper’owskich, ale także np.: C, FORTRAN, PASCAL. Umożliwia polskojęzyczną pracę dowolnego programu – przez uzyskanie i obsługę polskich znaków na ekranie, klawiaturze i drukarce, w dowolnym z kodów przyjętych w Polsce:

LATIN_2 – jedyny oficjalny kod polskich liter, stosowany przez IBM, Emix, Elwro,
MAZOVIA – jak sama nazwa wskazuje,
CSK – Computer Studio Kajkowscy (Mbank),
DHN – Dom Handlowy Nauki,
CYFROMAT –
MICROVEX –
UNIA –
NONE – nie używa żadnego kodu.

EMUlator jest zewnętrzny względem obsługiwanego programu – nie ma dla niego znaczenia w której wersji Clipper’a został
skompilowany program. Istotne jest tylko aby program kontaktował się z EMUlatorem w ustalony sposób. Program pracujący pod EMUlatorem może całkowicie poprawnie pracować bez EMUlatora – oczywiście bez polskich liter.

Dla skorzystania EMUlatora konieczne jest tylko posiadanie karty Hercules z dostępnymi obydwiema stronami graficznymi. Praktycznie znaczy to, że nie może być zainstalowana oprócz HGC karta CGA.

Wraz z EMUlatorem dostarczane są funkcje pozwalające użytkownikowi na uzyskanie całkowicie polskojęzycznego programu, co oznacza całkowicie polskojęzyczne sortowanie i wyszukiwanie.

Użytkownik może także w programie w łatwy sposób wywoływać wewnętrzne funkcje EMUlatora, jak np. definiować własne znaki.

EMUlator umożliwia przemienne stosowanie dowolnego standardu polskich liter, co może być niezwykle wygodne np.: przy pisaniu oprogramowania dla użytkowników stosujących różne standardy.

EMUlator nie jest rezydentny – więc nie zajmuje pamięci wtedy gdy nie jest potrzebny, gwarantuje, że po zakończeniu potomnego programu (nie ma znaczenia w jaki sposób się on zakończy) zostanie przywrócony normalny stan DOSa.

EMUlator instaluje własne przerwanie, pozwalające programowi użytkownika na bezpośrednie korzystanie z jego funkcji. Dostarczona dokumentacja oraz dostarczone wersje źródłowe funkcji pozwolą użytkownikowi znającemu asembler lub C na swobodne pisanie własnych funkcji korzystających z EMUlatora.

*═══════════════════════════════════════════════════════*

URUCHOMIENIE.

EMUlator uruchamia się w postaci:

EMU [-kod] nazwa_programu_do_uruchomienia [jego_argumenty…]

– kod w postaci minus i nazwa kodu polskich liter, tak jak to zostało podane powyżej. EMUlator domyślnie używa LATIN_2.
– nazwa_programu_do_uruchomienia – nazwa zbioru, który ma zostać uruchomiony jako potomek EMUlatora.
– jego_argumenty – o ile są podane to zostaną przekazane potomkowi.

Przykład:

Aby uruchomić program ‚kadry.exe’ trzeba napisać:
C:>EMU kadry.exe <───┘ Aby uruchomić DOSa w wersji polskiej – o ile nie masz zainstalowanego ANSI.SYSa ! – trzeba napisać: C:>EMU command <───┘ Możesz wypisać ten właśnie dokument po polsku pisząc: C:>type pg.doc >prn.

Zakończenie pracy uzyskasz pisząc:
C:>exit <───┘. Wraz z EMUlatorem został dostarczony przykładowy program ‚^demo.prg’ oraz ‚^clpm.bat’ służący do jego kompilacji. Uwaga: EMUlator szuka zbioru podanego do uruchomienia po ścieżce – PATH. Nie jest możliwe bezpośrednie uruchamianie zbiorów typu .BAT przez EMUlator. EMUlator pozwala uruchomić program o nazwie z dowolnym rozszerzeniem, nie tylko .COM i .EXE, ale próba uruchomienia zbioru tekstowego może skończyć się bardzo źle (nie wiadomo co on zrobi podczas wykonania, ale na pewno nic dobrego). *═══════════════════════════════════════════════════════* ZAKOŃCZENIE PRACY. Program potomny po wykonaniu się zawsze powraca do EMUlatora, niezależnie od sposobu zakończenia, a EMUlator przywraca poprzedni stan systemu i wyświetla końcowe informacje. W pierwszym wierszu: nazwę programu, numer wersji i numer seryjny. W drugim: nazwę używanego kodu polskich liter, oraz – jeżeli potomny program został poprawnie uruchomiony to podawany jest jego kod wyjścia w postaci dwóch liczb – pierwsza określa sposób zakończenia programu przez DOSa (0 – normalne, 1 – Ctrl-C, 2 – błąd urządzenia, 3 – program rezydentny), a druga jest to kod podawany przez program przy zakończeniu, w Clipper’ze obsługiwany funkcją ERRORLEVEL(). Jeżeli potomny program nie został uruchomiony to podawany jest komunikat określający rodzaj błędu, raportowanego przez funkcję SPAWN. Uwaga: Jeżeli program Clipper’owski załamie się podczas wykonania nagłówka, a przed rozpoczęciem właściwego programu – to zwrócony kod wyjścia nie będzie miał nic wspólnego z określonym przez ERRORLEVEL() w programie. Typowe błędy to: ENOENT – podany program nie został znaleziony ani w bieżącym katalogu, ani na ścieżce – albo go rzeczywiście nie ma, albo to literówka w jego nazwie. ENOMEM – jest za mało pamięci dla uruchomienia potomka – najpewniej masz jakiś program rezydentny – spróbuj go usunąć, wyjdź z NC, jeżeli w nim jesteś. ENOEXEC – to, co chcesz uruchomić, zdaniem DOSa, nie da się uruchomić. Jeżeli to rzeczywiście jest program typu EXE, to prawdopodobnie jest uszkodzony. E2BIG – nie powinno się pojawić, ale jeżeli się pojawi to sygnalizuje przepełnienie (prawdopodobnie) obszaru przeznaczonego na zmienne ustawiane przez SET – sprawdź to. Inne komunikaty świadczą, że prawdopodobnie EMUlator jest uszkodzony – czy to na dysku, czy to przez uruchomiony program. *═══════════════════════════════════════════════════════* SIDEKICK i inne rezydentne programy. Możliwe jest używanie wraz z EMUlatorem także Sidekick’a – istotne jest tylko, aby kończyć pracę z nim przez ESC, co przywróci właściwy tryb pracy ekranu, zmieniony przez SK. Nie jest wykluczone powstanie konfliktów pomiędzy niektórymi programami rezydentnymi a EMUlatorem przy obsłudze klawiatury. Dotąd nie zetknąłem się z czymś takim, ale jeżeli wystąpi to spróbuj empiryczne ustalić, czy zmiana kolejności instalowania programów nie zlikwiduje problemu. *═══════════════════════════════════════════════════════* INFORMACJE SZCZEGÓŁOWE: EKRAN. Podczas pracy programu ekran jest przełączany w tryb graficzny (640×350), znaki na ekranie są wyświetlane są jako graficzne, symulowana jest także sprzętowa obsługa kursora. Program użytkowy nie zdaje sobie z tego sprawy – dla programu użytkowego jest to monochromatyczny mod tekstowy 80×25 (mod 7). Po zakończeniu programu użytkowego jest przywracany poprzedni stan ekranu. Program pisze bezpośrednio do rejestrów kontrolera wizji, oraz samodzielnie wykonuje HGC FULL. Problemem jest interpretowanie atrybutów ekranu tekstowego w trybie graficznym. Program przedstawia znaki o podwyższonej jaskrawości oraz migające jako italiki (pochylone). Nie ma przeszkód przed dowolnym rozszerzeniem ilości fontów, spowoduje to jednak wzrost wielkości programu o więcej niż 256*14=3584 bajty, jeżeli życzysz sobie tego – skontaktuj się z autorem. EMUlator pozwala uzyskać dwa rodzaje kursora: stały oraz migający. EMU_CALL(33,0) && uruchomienie kursora NIE migającego Interpretacja atrybutów – Clipper. EMUlator musi przekształcić atrybuty ekranu do postaci odpowiedniej dla ekranu graficznego – tworzonego przez czarne i białe punkty. W clipper’ze dla tej wersji EMUlatora optymalną konwersję uzyskuje się dla: SETCOLOR(„W/N ,N+/U,,W,N/W”) Atrybut W dla BORDER’u jest zalecany, ponieważ określa on kolor znaków przy pracy z EMU.cga. Jeżeli życzysz sobie EMUlatora dostosowanego do swoich potrzeb – skontaktuj się z autorem, adres jest na końcu tekstu. *══════════════════════════════════════════════════════* INFORMACJE SZCZEGÓŁOWE: KLAWIATURA. Program obsługuje klawiaturę w sposób znany jako ‚klawiatura programisty’. Oznacza to, że literę ‚ą’ uzyskuje się naciskając klawisz ‚a’ wraz z klawiszem ALT, a literę ‚Ą’ – klawisz ‚A’ wraz z klawiszami SHIFT i ALT. (Litery ‚ż’ i ‚ź’ są przyporządkowane klawiszom ‚Z’ i ‚X’.) Klawisz ALT spełnia funkcję POLSKIEGO SHIFTa. Obsługę polskich liter włącza i wyłącza się klawiszem ScrollLock – co pozwala na używanie także kombinacji typu ALT-A, czy ALT-C, co jest niezbędne w wielu programach. Przez użycie EMU_CALL(69, 1) uzyskuje się wymuszenie polskiej klawiatury – stan ScrollLock nie ma wtedy znaczenia. Uwaga: Przez użycie EMU_CALL(71, 1) podczas aktywności polskich liter na klawiaturze: lewy shift oraz prawy shift wraz z klawiaturą numeryczną, szarym ‚+’ i ‚-‚ będą wypisywać znaki tworzące ramki, odpowiednio: pojedynczą i podwójną. Wraz z CapsLock wypisują znaki łączące ramki pojedyncze z podwójnymi. Także z klawiszami Esc, Backspace i Del są związane symbole semigraficzne. *═══════════════════════════════════════════════════════* INFORMACJE SZCZEGÓŁOWE: DRUKARKA. Przy drukowaniu polskich liter mogą wystąpić następujące sytuacje: 1) Drukarka ma zaprogramowany zestaw znaków. Rozwiązanie najprostsze w eksploatacji, ale często niewygodne do uzyskania – gdy oznacza konieczność przeprogramowania wlutowanych EPROMów, a trudne szczególnie dla egzotycznych drukarek. Zaletą są dobre kształty znaków, wadą przywiązanie do jednego kodu – szczególnie w warunkach krajowej wielości obowiązujących standardów. 2) Zaprogramowanie polskich liter na drukarce. Po każdym włączeniu drukarki należy wysłać do niej ciąg znaków definiujących polskie litery. Kody i kształty polskich liter określane są przy ich definiowaniu i mogą być różne dla różnych programów. 3) Metoda BackSpace. Polska litera powstaje poprzez wydrukowanie angielskiego odpowiednika, cofnięcie głowicy przez BS i wydrukowanie odpowiedniego ogonka. Przykładowo, ‚ą’ powstaje z ‚a’, BS, ‚,’. Wielką zaletą tej metody jest to, że działa praktycznie na wszystkich drukarkach, dając przyzwoite kształty polskich liter oraz tolerując wszelkie błędy wydruku. Metoda ta jest męcząca dla drukarki, co też jest jej największą wadą, a przy większej ilości polskich liter w tekście powolna. Ta metoda jest ustawiana przy starcie EMUlatora. Załączenie tej funkcji w programie uzyskuje się przez: EMU_CALL(129, 1) 4) Metoda dwu wierszy. Tekst jest drukowany wierszami. Jeżeli w drukowanym wierszu znajduje się polska litera to wiersz drukowany jest dwa razy: w pierwszym przebiegu angielskie odpowiedniki, w drugim przebiegu na pierwszy wiersz nadrukowywane są ogonki. Metoda nie obciąża drukarki, co jest jej największą zaletą. Wadą metody jest konieczność obsługi przez dosyć skomplikowany program, posiadający co najmniej jeden bufor, o długości większej od długości drukowanych wierszy. Jeżeli program obsługi będzie w miarę uniwersalny, to nie będzie mógł rozumieć większości kodów sterujących drukarki (gdyby chciał je rozumieć, to musiałby być funkcjonalną kopią programu sterującego drukarką). Użytkownik musi wydruki projektować biorąc pod uwagę istnienie i działanie programu. Jeżeli używasz tej metody, to pamiętaj, że handler drukarki rozpoznaje tylko typowe kody sterujące – żadnego z rozpoczynających się od ESCape (DODATEK C). Jeżeli stosujesz wielokrotne nadrukowywanie dla uwydatnienia tekstu, to w tej metodzie to nie zadziała. Załączenie tej funkcji w programie uzyskuje się przez: EMU_CALL(129, 2) *═══════════════════════════════════════════════════════* DODATEK A. Funkcje użytkownika. EMU_CALL(ax, bx, cx, dx, si, di) Wywołanie EMUlatora – to znaczy wykonanie przerwania INT 64h z podanymi wartościami w rejestrach – zgodnie z DODATKIEM B. Funkcja EMU_CALL() może być wywołana niezależnie od obecności EMUlatora. Na wejściu: ax – bx – cx – dx – si – di – Na wyjściu: bx – EMU_DEF(font, znak, def_string) Definiowanie własnych znaków przez użytkownika. Na wejściu: font – numer fontu, tutaj 0 znak – numer znaku 0..255 def_string – 14 znakowy (dla HGC) łańcuch zawierający definicję Na wyjściu: [ NIC ] ISEMU() Sprawdzenie obecności EMUlatora. Na wejściu: [ NIC ] Na wyjściu: .T. – EMUlator jest obecny .F. – nie ma EMUlatora PL_INIT() Inicjalizacja funkcji obsługujących polskie litery. Dane są czytane z EMUlatora, konieczne jest wywołanie tej funkcji na początku programu oraz po zmianie kodu polskich liter. Na wejściu: [ NIC ] Na wyjściu: .T. – EMUlator jest obecny .F. – nie ma EMUlatora PL_UPPER() Zamiana na duże litery, z uwzględnieniem aktualnych polskich. Na wejściu: Tekst Na wyjściu: Tekst PL_LOWER() Zamiana na małe litery, z uwzględnieniem aktualnych polskich. Na wejściu: Tekst Na wyjściu: Tekst PL_MAP() Zamienia na angielskie odpowiedniki podane polskie, z uwzględnieniem aktualnych polskich („Kądziołka”->”Kadziolka”). Funkcja pozwala wyszukiwać w zbiorze polskojęzyczne teksty, niezależnie od tego, czy zostały wpisane z polskimi literami, czy też bez. Przy indeksowaniu pozwala uzyskać przyzwoite polskojęzyczne uporządkowanie.

Przykładowo: ciągi znaków ‚AĄB’, ‚AĄA’, ‚AAB’ zostaną przez PL_MAP() uporządkowane następująco: ‚AĄA’, ‚AAB’, ‚AĄB’.

Na wejściu:
Tekst

Na wyjściu:
Tekst

PL_ORD()
Przekształca podany tekst na łańcuch zawierający bajty określające bezwzględną kolejność podanych znaków – z uwzględnieniem polskich liter. Użycie funkcji przy indeksowaniu spowoduje polskojęzyczne uporządkowanie zbioru.

Przykładowo: ciągi znaków ‚AĄB’, ‚AĄA’, ‚AAB’ zostaną przez PL_ORD() uporządkowane następująco: ‚AAB’, ‚AĄA’, ‚AĄB’.

Na wejściu:
Tekst

Na wyjściu:
Tekst

UWAGA:
W zbiorze $emu.c zawarte są dwie wersje niektórych funkcji, jedna operująca na kopii przekazanego łańcucha, druga bezpośrednio na samym łańcuchu.

*═══════════════════════════════════════════════════════*
DODATEK B.
Przerwanie EMUlatora.

EMUlator podczas pracy instaluje przerwanie 0x64, poprzez które potomny program uzyskuje dostęp do EMUlatora.

Sposób wywołania:

Na wejściu:

rejestr AX – numer funkcji
rejestr BX – główny argument
rejestry CX, DX, SI, DI – argumenty pozostałe
INT 64h

Na wyjściu:

rejestry BX, CX, DX, SI, DI
rejestr AX – jeżeli równy 0xffff, to brak funkcji którą wywoływano
rejestr BX – w nim zwracana jest główna wartość
rejestry CX, DX, SI, DI – pozostałe dane (o ile takowe są)

Opis wszystkich funkcji EMUlatora znajduje się w zbiorze ’emu_func.doc’.

*═══════════════════════════════════════════════════════*
DODATEK C.

Liniowy handler drukarki.
Poniżej podane jest, w jaki sposób liniowy handler drukarki traktuje znaki o kodach 0..31 i 127.

Znaki przesyłane do drukarki bez zmian – jednokrotnie.

Kod 0 – NULL
Kod 1 – SOH
Kod 2 – STX
Kod 3 –
Kod 4 –
Kod 5 –
Kod 6 –
Kod 7 – BEL
Kod 16 – DLE
Kod 17 – DC1
Kod 19 – DC3
Kod 21 –
Kod 22 – SYN
Kod 23 – ETB
Kod 25 – EM
Kod 26 – SUB
Kod 27 – ESC
Kod 28 – FS
Kod 29 – GS
Kod 30 – RS
Kod 31 – US

Znaki przesyłane w obydwu przebiegach.

Kod 8 – BS
Kod 9 – HT
Kod 14 – SO
Kod 15 – SI
Kod 18 – DC2
Kod 20 – DC4
Kod 127 – DEL

Znaki przesyłane i traktowane przez handler jako sterujące.

Kod 10 – LF wysuw papieru o jeden wiersz, powoduje wydruk.
Kod 11 – VT tabulacja pionowa, powoduje wydruk.
Kod 12 – FF wysuw do nowej strony, powoduje wydruk.
Kod 13 – CR powoduje wydruk, także bufora wewnętrznego.
Kod 24 – CAN skasowanie bufora drukarki, także wewnętrznego

Przy próbie przekroczenia wielkości bufora wewnętrznego jest on kasowany i blokowany, aż do rozpoczęcia nowego wiersza.
*═══════════════════════════════════════════════════════*
DODATEK D.

Kolejność polskich liter.
Polskie litery są umieszczone w wewnętrznych buforach programu w poniższej kolejności: „ĄĆĘŁŃÓŚŹŻ”, „ąćęłńóśźż”. Kolejność ta obowiązuje także dla funkcji sortujących.
*═══════════════════════════════════════════════════════*
DODATEK E.

Przygotowanie programu do współpracy z EMUlatorem – Clipper.

UWAGA:

Wśród zbiorów dostarczanych z EMUlatorem znajduje się ‚^DEMO.PRG’, będący przykładowym programem prezentującym podstawowe zastosowania funkcji użytkownika.
Dla wstępnego uruchomienia wystarczy linkować program z PCBIOS.OBJ. Pozwoli to na ewentualne skorygowanie ustawienia atrybutów (SET COLOR ) w programie, tak aby uzyskać jego właściwą postać przy pracy z EMUlatorem.
Następnym etapem jest wpisanie polskich liter do formatek i komunikatów programu.
Taki program będzie już pozwalał wprowadzać dane po polsku, a także będzie pisał na ekranie i drukarce po polsku. Jeżeli pola, w których są polskie litery nie są używane do indeksowania lub wyszukiwania, to może to być już koniec przeróbek!
Aby uzyskać polskojęzyczne sortowanie i wyszukiwanie trzeba oprócz PCBIOS.OBJ zlinkować z programem EMU.LIB (DODATEK G).
Na początku programu trzeba ustawić parametry pracy EMUlatora przez wywołania funkcji EMU_CALL().

*
IF ISEMU() && tylko wtedy, gdy jest EMUlator
*
SETCOLOR(„W/N ,N+/U,,W,N/W”)
*
EMU_CALL(33, 1) && kursor migający
EMU_CALL(65, 1) && kod aktualnie obowiązujących
&& polskich znaków – LATIN 2
EMU_CALL(69, 1) && polskie litery niezależne od ScrollLock
EMU_CALL(129, 2)&& wierszowa obsługa polskich liter
*
* Potem należy wywołać PL_INIT().
PL_INIT()
*
ELSE
* można uniemożliwić uruchomienie programu bez EMU,
* albo ustawić parametry programu dla pracy bez EMU.
*
?
? „*** Ten program wymaga EMUlatora ***”
?
QUIT
ENDIF
*

Jeżeli w bazie dane mają być zapisane dużymi literami to umieścić PL_UPPER() bezpośrednio w instrukcji REPLACE, co da pewność, że zostaną przekształcone.
Jeżeli stosuje się indeksowanie po polach mogących zawierać polskie litery użyć funkcji PL_MAP() albo PL_ORD().
Funkcja PL_MAP() przekształca polskie litery na angielskie odpowiedniki, co oznacza, że np. z ‚Kądziołki’ powstanie ‚Kadziolka’. Użycie tej funkcji do indexowania i wyszukiwania spowoduje, że: dane zostaną posortowane sensownie, ale nie doskonale – ‚ą’ będzie traktowane dokładnie jak ‚a’, ale też program będzie tolerował polskie dane wpisane po angielsku – np. wpisane przed użyciem EMUlatora, jak i błędy przy wprowadzaniu spowodowane brakiem przyzwyczajenia do używania polskich liter.

Przykład:
USE osoby
INDEX ON Pl_map(Pl_upper(nazwisko)) TO nazw
x = „Kądziołka”
x = Pl_upper(x)
SEEK Pl_map(x) * LOCATE FOR Pl_map(x) == Pl_map(osoby->nazwisko)
? imie

Funkcja PL_ORD() przekształca polskie litery na kody, określające w jednoznaczny sposób ich kolejność. Użycie tej
funkcji do indexowania i wyszukiwania spowoduje, że program będzie pracował CAŁKOWICIE po polsku.

Przykład:
USE osoby
INDEX ON Pl_ord(Pl_upper(nazwisko)) TO nazw
x = „Kądziołka”
x = Pl_upper(x)
SEEK Pl_ord(x)
? imie

Podobnie należy postąpić przy wyszukiwaniu (SEEK, LOCATE), oraz przy porównywaniu tekstów polskojęzycznych (IF PL_MAP(x) == PL_MAP(y) ).
Opisane funkcje mogą być wywoływane mimo braku EMUlatora – działają wtedy angielskojęzycznie.
Powyższe wskazówki są wyłącznie orientacyjne – każdy program jest inny i najważniejsze, to wiedzieć, co chce się osiągnąć.
*═══════════════════════════════════════════════════════*
DODATEK F.

Kompilacja.
Poniżej przedstawiony jest BATCH służący do kompilacji programów korzystających z funkcji użytkownika.

Założenia:

W katalogu C:\CLP znajduje się Clipper, czyli CLIPPER.EXE,
CLIPPER.LIB, EXTEND.LIB, DEBUG.OBJ, PCBIOS.OBJ.

EMU.LIB znajduje się w bieżącym katalogu.

LINK.EXE i TLIB.EXE są osiągalne na ścieżce.

Poniższy BATCH nazywa się ECLP.BAT i jest osiągalny na ścieżce.

@ECHO OFF C:\CLP\CLIPPER %1 %2 IF ERRORLEVEL 1 GOTO END ECHO .
rem ————————- rem
rem Ta pozycja ukazuje linkowanie przy pomocy LINKa.
rem (LINK ma duże możliwości, ale jest wolniejszy od TLINKa)
rem link %1+c:\clp\debug+c:\clp\pcbios/noe/noi/se:512/e/far,,nul.map,c:\clp\clipper+c:\clp\extend+EMU.LIB
rem ————————-
rem
rem Ta pozycja ukazuje linkowanie przy pomocy TLINKa.
rem (TLINK jest bardzo szybki ale głupi – może zakłócać działanie
rem niektórych funkcji !) tlink %1+c:\clp\debug+c:\clp\pcbios,,,c:\clp\clipper+c:\clp\extend+EMU.LIB
/c rem ————————- :END IF EXIST %1.OBJ ERASE
%1.OBJ ECHO .

Jeżeli chcesz skompilować przy pomocy powyższega BATCHa program nazywający się ‚TEST.PRG’ to napisz ‚ECLP test <───┘’ (nazwa programu BEZ rozszerzenia).
*═══════════════════════════════════════════════════════*
DODATEK G.

Biblioteka.
Wraz z EMUlatorem są dostarczone zbiory ‚$EMU.C’ i ‚EMU.LIB’. ‚EMU.LIB’ zawiera funkcje, które po dołączeniu, do kompilowanego programu pozwolą wywoływać funkcje EMUlatora, jak i polskojęzyczne warianty niezbędnych funkcji CLIPPER’owskich, a ‚$EMU.C’ zawiera ich postać źródłową. Biblioteka ta nie ma charakteru ostatecznego – jest przykładem i propozycją dla użytkownika jak napisać własne funkcje.

EMU_CALL(ax, bx, cx, dx, si, di) EMU_DEF(font, znak, def_string)

ISEMU() PL_INIT() PL_UPPER() PL_LOWER() PL_MAP() PL_ORD()

FULL_CRS() – załączenie dużego kursora SET_CRS(top, bottom) – zalączenie kursora o podanych wymiarach

Opis EMU, wersja 3.0 tk.

Makefile:

DEBUG=0
MASM_PATH=$(_)/masm
#VERSION=-DTREND
#VERSION=-DCLIPPER
#------------------------------------------------#
#!if $(DEBUG)==1
#C_FLAGS= -AS -c
#D_FLAG= -Mx -Zi
#L_FLAGS= /CPAR:1/FAR/NOI/COD/MAP
#------------------------------------------------#
#!else
C_FLAGS= -AS -Oti -c
D_FLAG= -Mx
L_FLAGS= /CPAR:1/FAR/NOI
#------------------------------------------------#
#!endif
emu.exe: emu.obj a1_emu.obj a2_emu.obj gpkey.obj
link emu.obj+a1_emu.obj+a2_emu.obj+gpkey.obj $(L_FLAGS);
C:/TOOLS/COPYR emu.exe
#
demu.exe:
cl $(C_FLAGS) -DDEMO $(VERSION) emu.c
$(MASM_PATH)/masm $(D_FLAG) -DDEMO $(VERSION) -I$(MASM_PATH) gpkey.asm;
$(MASM_PATH)/masm $(D_FLAG) -DDEMO $(VERSION) -I$(MASM_PATH) a1_emu.asm;
$(MASM_PATH)/masm $(D_FLAG) -DDEMO $(VERSION) -I$(MASM_PATH) a2_emu.asm;
link emu.obj+a1_emu.obj+a2_emu.obj+gpkey.obj $(L_FLAGS), demu.exe;
C:/TOOLS/COPYR demu.exe
del *.obj
#
emu.obj: emu.c
cl $(C_FLAGS) $(VERSION) emu.c
gpkey.obj: gpkey.asm
$(MASM_PATH)/masm $(D_FLAG) $(VERSION) -I$(MASM_PATH) gpkey.asm;
a1_emu.obj: a1_emu.asm
$(MASM_PATH)/masm $(D_FLAG) $(VERSION) -I$(MASM_PATH) a1_emu.asm;
a2_emu.obj: a2_emu.asm
$(MASM_PATH)/masm $(D_FLAG) $(VERSION) -I$(MASM_PATH) a2_emu.asm;

Jeden z modułów:

NAME a1_emu
INCLUDE mixed.inc
.MODEL small
cLang=1
;
CHAR_HEIGHT EQU 14
FONT_SIZE EQU 256*CHAR_HEIGHT
;
;
OFFSET_SUM1 EQU 137;/* SECURITY */
OFFSET_SUM2 EQU 112;/* SECURITY */
OFFSET_KEY EQU 81;/* SECURITY */
USER_NAME_LENGTH EQU 76;/* SECURITY */
;
;
_TEXT SEGMENT WORD PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT WORD PUBLIC 'DATA'
;------------------------------------------------------------------
EXTRN _crs_top:BYTE, _crs_bot:BYTE
EXTRN _crs_row:BYTE, _crs_col:BYTE
EXTRN _crs_on:BYTE

EXTRN _display_buffer:BYTE

EXTRN _font_tbl_norm:BYTE
EXTRN _font_tbl_pol:BYTE
EXTRN beg_rows:WORD
;
EXTRN _pol_tbl:BYTE;
EXTRN _eng_tbl:BYTE;
EXTRN _dia_tbl:BYTE;
EXTRN _map_char:BYTE, _map_dia:BYTE;
EXTRN _old_v_10:DWORD
EXTRN _old_v_17:DWORD
;
EXTRN _passwd:BYTE;/* SECURITY */
EXTRN _user_name:BYTE;/* SECURITY */
EXTRN _sum1:WORD;/* SECURITY */
;——————————————————————
_DATA ENDS
DGROUP GROUP _DATA

ASSUME CS: _TEXT, DS: DGROUP, SS: DGROUP

_TEXT SEGMENT
ASSUME CS: _TEXT
;——————————————————————
hProc , , reg_AX:WORD, reg_DX:WORD
;
mov AX, reg_AX
mov DX, reg_DX
pushf
CALL DWORD PTR _old_v_17
;
hRet
hEndp
;——————————————————————
; jeżeli znak jest polski, to zwraca !0 i (inaczej 0)
;wpisuje do map_char angielski odpowiednik,
;a do map_dia odpowiedni ogonek.
hProc , , char:BYTE
;
test char, 80h
jz no_map; polskie litery NA PEWNO >= 80h
;
mov AX, DS
mov ES, AX
;
mov AL, char
mov DI, OFFSET _pol_tbl
mov CX, 18
cld
repne scasb
je map_it
no_map:
sub AX, AX
jmp short end_map
;
map_it:
sub DI, OFFSET _pol_tbl + 1
mov AL, DS:[DI + OFFSET _eng_tbl]
mov _map_char, AL
;
mov AL, DS:[DI + OFFSET _dia_tbl]
mov _map_dia, AL
;
end_map:
hRet
hEndp
;——————————————————————
hProc ; AX != 0 dla HGC
;
int 11h
and AX, 0030h
cmp AX, 0030h
je is_mono
sub AX, AX
;
is_mono:
CALL _decode;/* SECURITY */
hRet
hEndp
;——————————————————————
; odczytuje pozycje kursora z biosa i wpisuje ją do zmiennych
hProc ,
;
mov AH, 03h
mov BH, 0
;
pushf
CALL DWORD PTR _old_v_10
;
mov _crs_row, DH
mov _crs_col, DL
;
hRet
hEndp
;——————————————————————
hProc ,
;
mov AH, 02h
mov BH, 0
;
mov DH, _crs_row
mov DL, _crs_col
;
pushf
CALL DWORD PTR _old_v_10
;
hRet
hEndp
;——————————————————————
hProc , , font:BYTE, char_no:BYTE, segm:WORD, offs:WORD
;
mov DI, OFFSET _font_tbl_norm
cmp font, 0
je lc_done
;
mov DI, OFFSET _font_tbl_pol
cmp font, 16
je lc_done
;
mov AX, 0ffffh
jmp short lc_quit
;
lc_done:
mov AX, CHAR_HEIGHT
mov BL, char_no
mul BL
add DI, AX ; DI wskazuje na znak w tablicy fontów
;
mov AX, CHAR_HEIGHT
push AX
push DI
push offs
push segm
CALL _from_far_cpy
add SP, 8
;
sub AX, AX
;
lc_quit:
;
hRet
hEndp
;——————————————————————
; kopiuje do EMU (DS:dst) z zewnątrz src_seg:src_off kount bajtów
hProc , , src_seg:WORD, src_off:WORD, dst_off:WORD, count:WORD
;
mov BX, dst_off
mov SI, src_seg
mov ES, SI
mov SI, src_off
;
mov CX, count
next_byte_cpy:
mov AL, BYTE PTR ES:[SI]
mov BYTE PTR [BX], AL
inc SI
inc BX
loop next_byte_cpy
;
hRet
hEndp
;——————————————————————
;——————————————————————
hProc , ;/* SECURITY */
;
mov DX, 0
mov BX, OFFSET _user_name
mov CX, USER_NAME_LENGTH
mov AH, DL
next_sum2:
mov AL, [BX]
add DX, AX
add BX, 1
loop next_sum2
;
mov AX, DX
;
hRet
hEndp
;——————————————————————
;——————————————————————
hProc ,
;
mov AX, 0b000h
mov ES, AX
mov DI, 0
MOV CX, 2000
mov AX, 0720h
cld
REP stosw
;
hRet
hEndp
;——————————————————————
hProc ,
;
mov AX, 0b800h
mov ES, AX
mov DI, 0
MOV CX, 4000h
mov AX, 0
cld
REP stosw
;
hRet
hEndp
;——————————————————————
; Scroll Window Up & Down
hProc , r_ax:WORD, r_bx:WORD, r_cx:WORD, r_dx:WORD
;
cli
mov AX, SP
push AX
sti
push BX
push CX
push DX
; push SP
push BP
push SI
push DI
;
mov AX, r_AX
mov BX, r_BX
mov CX, r_CX
mov DX, r_DX
;
pushf
CALL DWORD PTR _old_v_10
;
pop DI
pop SI
pop BP
; pop SP
pop DX
pop CX
pop BX
cli
pop AX
mov SP, AX
sti
;
hRet
hEndp
;——————————————————————
;——————————————————————
; Read Character and Attribute at Cursor
hProc ,
;
sub BH, BH
mov BL, _crs_col
shl BL, 1 ; BX = col*2
;
mov AL, 160
mov CL, _crs_row
mul CL ; AX = adres wiersza
;
add BX, AX ; BX = offset do ekranu
;
mov AX, 0b000h
mov DS, AX
;
mov AX, [BX]
; AH – attrib
; AL – ASCII
;
IFDEF DEMO ; Clear TRAP flag
push AX
pushf
pop AX
and AX, 0feffh
push AX
popf
pop AX
ENDIF
hRet
hEndp
;——————————————————————
; Write Character and Attribute at Cursor
hProc , , char:BYTE, attrib:BYTE, times:WORD
;
push SI
;
sub DH, DH
mov DL, _crs_col
mov BH, DL
shl DL, 1 ; DX = col*2
;
mov AL, 160
mov BL, _crs_row
mul BL ; AX = adres wiersza
;
add AX, DX
mov DI, AX ; DI = offset do ekranu
;
mov AX, 0b000h
mov ES, AX
;
mov AL, char ;
mov AH, attrib ;
mov SI, AX ; przechować, display_char niszczy AX
mov CX, times
;
cld
;
next_dsp_9:
mov AX, SI
stosw ; mov AX, ES:[DI], DI+=2
; AH – attrib
; AL – ASCII
;
push SI ; attrib + ASCII
mov DL, BH
push DX ; col
push BX ; row
CALL _display_char ;( BL, BH, AX)
add SP, 6
;
inc BH ; col++
cmp BH, 80
jb same_row_9
mov BH, 0 ; col=0;
inc BL ; row++
same_row_9:
LOOP next_dsp_9
;
pop SI
;
hRet
hEndp
;——————————————————————
;——————————————————————
hProc , ;/* SECURITY */
;
mov DX, [_sum1]
mov BX, OFFSET _user_name
mov AH, 0
mov CX, USER_NAME_LENGTH
next_sum1:
mov AL, [BX]
add DX, AX
inc BX
loop next_sum1
;
xchg AX, DX
;
hRet
hEndp
;——————————————————————
;——————————————————————
; Write Character at Cursor
hProc , , ascii:BYTE, times:WORD
;
sub DH, DH
mov DL, _crs_col
mov BH, DL
shl DL, 1 ; DX = col*2
;
mov AL, 160
mov BL, _crs_row
mul BL ; AX = adres wiersza
;
add AX, DX
mov DI, AX ; DI = offset do ekranu
;
mov AX, 0b000h
mov ES, AX
;
mov DL, ascii ; DL – ascii
mov CX, times
;
cld
;
next_dsp_a:
;
mov AX, ES:[DI] ; AH – attrib, AL – ASCII
mov AL, DL ; ascii do wypisanie
;
stosw ; mov AX, ES:[DI], DI+=2
;
push AX ; attrib + ASCII
mov AL, BH
push AX ; col
push BX ; row
CALL _display_char ;( BL, BH, AX)
add SP, 6
;
inc BH ; col++
cmp BH, 80
jb same_row_a
mov BH, 0 ; col=0;
inc BL ; row++
same_row_a:
LOOP next_dsp_a
;
hRet
hEndp
;——————————————————————
; Write Character in TTY Mode
hProc , , ascii:BYTE
hRet
hEndp
;——————————————————————
;——————————————————————
hProc , , src_addr:WORD, dst_addr:WORD, llength:WORD
;
mov AX, 0b000h
mov DS, AX
mov SI, src_addr
mov ES, AX
mov DI, dst_addr
;
mov CX, llength
cld
rep movsw
;
hRet
hEndp
;——————————————————————
hProc , , dst_addr:WORD, llength:WORD, filler:WORD
;
mov AX, 0b000h
mov ES, AX
mov DI, dst_addr
;
mov AX, filler
mov AL, ‚ ‚
mov CX, llength
cld
rep stosw
;
hRet
hEndp
;——————————————————————
;——————————————————————
; sumuje dla podanego fontu bajty drugiego jego znaku
; do sprawdzenia, czy font był zdefiniowany wewnątrz programu
; jeżeli nie (suma == 0): to program sam musi go zdefiniwać
hProc , , addr:WORD
;
mov SI, addr
add SI, CHAR_HEIGHT
;
sub BX, BX
cld
mov CX, 7
;
test_next:
lodsw
add BX, AX
loop test_next
;
mov AX, BX
;
hRet
hEndp
;——————————————————————
hProc
; BX – ascii+attrib
; CX – licznik znaków
; DX –
; ES:DI – b000 – text
;
sti
;
push ES
push DI
push BX
push CX
push DX
;
cld
;
mov AX, 0b000h
mov ES, AX
mov DI, 0
;
mov CX, 0
next_pair:
;
mov BX, ES:[DI]
inc DI
inc DI
mov AX, CX
mov DL, 80
div DL
; AH-col, AL, row
mov DL, AH ; col
push BX
push DX
push AX
CALL _display_char
add SP, 6
;
inc CX
cmp CX, 2000
jb next_pair
;
;
pop DX
pop CX
pop BX
pop DI
pop ES
;
hRet
hEndp
;——————————————————————
hProc
;DS:SI – tablica fontów
;DS:BX – tablica adresow poczatkow wierszy –> BP
;ES:DI – b800:, DI – col
; CL – row
;
push ES
push DI
push DS
push SI
push DX
push CX
push BX
push AX
push BP
;
;—————————————————>
;
; wpisac adres dla ekranu graficznego DI=CX==col
sub CH, CH
mov CL, _crs_col
; shl CL,1 ; *2
mov DI, CX
;
;—————————————————>
; obliczenie adresu znaku na ekranie
mov AX, 0b000h
mov ES, AX
;
mov AL, 160
mul _crs_row ; AX=row*160
;
mov BX, AX ; BX=row*160
add BX, CX ; BX= BX + col
add BX, CX
;
; wczytanie znaku z ekranu
mov BX, ES:[BX] ; asc, attr
;
mov AX, CHAR_HEIGHT
mul BL ; ascii
;
;—————————————————>
;
mov BL, BH ; kopia
and BL, 70h
cmp BL, 70h
je char_reversed
mov CL, 0ffh
jmp short cl_selected
char_reversed:
sub CL, CL ; CL==0 znak w rewersji ==> cursor normalny
cl_selected:
;
mov SI, OFFSET _font_tbl_norm
add SI, AX
;
;—————————————————>
; obliczyc poczatek tablicy adresow dla podanego wiersza
; BEGROWS ma po 2 bajty – WORD
mov AX, CHAR_HEIGHT*2
mov BL, _crs_row
mul BL
mov BP, OFFSET DS:beg_rows
add BP, AX
;
; mov BP, OFFSET DS:beg_rows
; mov AL, _crs_row
; add AL, AL
; sub AH, AH
; add BP, AX
;
;—————————————————>
;
; adres segmentu ekranu graficznego
mov DX, 0b800h
mov ES, DX
;
;—————————————————>
;
mov DH, _crs_top
mov DL, _crs_bot
;
;—————————————————>
cld
;—————————–*
;—————————–*
lodsb ; tablica fontów
mov BX, DS:[BP] ; beg rows
cmp DH, 0
ja no_crs_00
cmp DL, 0
jb no_crs_00
xor AL, CL ; CL==0 nic, CL=ff reversja
; not AL
no_crs_00:
mov ES:[BX+DI], AL
inc BP
inc BP
;
;—————————–*
lodsb
mov BX, DS:[BP]
cmp DH, 1
ja no_crs_01
cmp DL, 1
jb no_crs_01
xor AL, CL
no_crs_01:
mov ES:[BX+DI], AL
inc BP
inc BP
;
;—————————–*
lodsb
mov BX, DS:[BP]
cmp DH, 2
ja no_crs_02
cmp DL, 2
jb no_crs_02
xor AL, CL
no_crs_02:
mov ES:[BX+DI], AL
inc BP
inc BP
;
;—————————–*
lodsb
mov BX, DS:[BP]
cmp DH, 3
ja no_crs_03
cmp DL, 3
jb no_crs_03
xor AL, CL
no_crs_03:
mov ES:[BX+DI], AL
inc BP
inc BP
;
;—————————–*
lodsb
mov BX, DS:[BP]
cmp DH, 4
ja no_crs_04
cmp DL, 4
jb no_crs_04
xor AL, CL
no_crs_04:
mov ES:[BX+DI], AL
inc BP
inc BP
;
;—————————–*
lodsb
mov BX, DS:[BP]
cmp DH, 5
ja no_crs_05
cmp DL, 5
jb no_crs_05
xor AL, CL
no_crs_05:
mov ES:[BX+DI], AL
inc BP
inc BP
;
;—————————–*
lodsb
mov BX, DS:[BP]
cmp DH, 6
ja no_crs_06
cmp DL, 6
jb no_crs_06
xor AL, CL
no_crs_06:
mov ES:[BX+DI], AL
inc BP
inc BP
;
;—————————–*
lodsb
mov BX, DS:[BP]
cmp DH, 7
ja no_crs_07
cmp DL, 7
jb no_crs_07
xor AL, CL
no_crs_07:
mov ES:[BX+DI], AL
inc BP
inc BP
;
;—————————–*
lodsb
mov BX, DS:[BP]
cmp DH, 8
ja no_crs_08
cmp DL, 8
jb no_crs_08
xor AL, CL
no_crs_08:
mov ES:[BX+DI], AL
inc BP
inc BP
;
;—————————–*
lodsb
mov BX, DS:[BP]
cmp DH, 9
ja no_crs_09
cmp DL, 9
jb no_crs_09
xor AL, CL
no_crs_09:
mov ES:[BX+DI], AL
inc BP
inc BP
;
;—————————–*
lodsb
mov BX, DS:[BP]
cmp DH, 0ah
ja no_crs_0a
cmp DL, 0ah
jb no_crs_0a
xor AL, CL
no_crs_0a:
mov ES:[BX+DI], AL
inc BP
inc BP
;
;—————————–*
lodsb
mov BX, DS:[BP]
cmp DH, 0bh
ja no_crs_0b
cmp DL, 0bh
jb no_crs_0b
xor AL, CL
no_crs_0b:
mov ES:[BX+DI], AL
inc BP
inc BP
;
;—————————–*
lodsb
mov BX, DS:[BP]
cmp DH, 0ch
ja no_crs_0c
cmp DL, 0ch
jb no_crs_0c
xor AL, CL
no_crs_0c:
mov ES:[BX+DI], AL
inc BP
inc BP
;
;—————————–*
lodsb
mov BX, DS:[BP]
cmp DH, 0dh
ja no_crs_0d
cmp DL, 0dh
jb no_crs_0d
xor AL, CL
no_crs_0d:
mov ES:[BX+DI], AL
; inc BP
; inc BP
;—————————–*
;
pop BP
pop AX
pop BX
pop CX
pop DX
pop SI
pop DS
pop DI
pop ES
;
hRet
hEndp
;——————————————————————
hProc ,
;ES:DI – b000:, DI – col
;
mov AX, 0b000h
mov ES, AX
;
sub BH, BH
mov BL, _crs_col
shl BL, 1 ; BX = col*2
;
mov AL, 160
mov DL, _crs_row
mul DL ; AX = adres wiersza
;
add BX, AX
;
mov AX, ES:[BX]
; AH – attrib
; AL – ASCII
;
push AX ; attrib + ASCII
mov AL, _crs_col
push AX ; col
mov AL, _crs_row
push AX
CALL _display_char ;( BL, BH, AX)
add SP, 6
;
hRet
hEndp
;——————————————————————
;——————————————————————
hProc , , row:BYTE, col:BYTE
;ES:BX – b000:
;
;
;—————————————————>
;
; wpisac adres dla ekranu graficznego CX==col
sub CH, CH
mov CL, col
;
;—————————————————>
; obliczenie adresu znaku na ekranie
mov AX, 0b000h
mov ES, AX
;
mov AL, 160
mul row ; AX=row*160
;
mov BX, AX ; BX=row*160
add BX, CX ; BX= BX + col
add BX, CX
;
; wczytanie znaku z ekranu
mov AX, ES:[BX] ; attr, asc
;
hRet
hEndp
;——————————————————————
;——————————————————————
hProc , ;/* SECURITY */
;
mov CX, (USER_NAME_LENGTH/2)
mov DX, WORD PTR [_passwd+OFFSET_KEY] ; kod dekodowania
mov BX, OFFSET _user_name
;
next_decode:
mov AX, [BX]
xor AX, DX
mov [BX], AX
inc BX
inc BX
loop next_decode
;
hRet
hEndp
;——————————————————————
;——————————————————————
;——————————————————————
hProc , , row:BYTE, col:BYTE, ascii:WORD
;DS:SI – tablica fontów
;ES:DI – b800:, DI – col
; CL – row
;
cld
;
mov AX, DS
mov ES, AX
;
; kopiowanie znaku do display_buffer
mov BX, ascii
mov DI, OFFSET _display_buffer
mov SI, OFFSET _font_tbl_norm
;
;
mov AX, CHAR_HEIGHT
mul BL ; ascii
add SI, AX
mov CX, CHAR_HEIGHT/2 ; kopiowanie słowami
rep movsw
;
mov CH, BH ; kopia do sprawdzeń – BX jest do czego innego
;
mov SI, OFFSET _display_buffer
;————————————-*
; test CH, 88h
; jz not_blink_bold
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
; mov BX, SI
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
;****************
test CH, 08h
jz not__bold
;**BOLD
mov BX, SI
;0
mov AX, [BX]
shr AH, 1
shr AL, 1
or [BX], AX
inc BX
inc BX
;1
mov AX, [BX]
shr AH, 1
shr AL, 1
or [BX], AX
inc BX
inc BX
;2
mov AX, [BX]
shr AH, 1
shr AL, 1
or [BX], AX
inc BX
inc BX
;3
mov AX, [BX]
shr AH, 1
shr AL, 1
or [BX], AX
inc BX
inc BX
;4
mov AX, [BX]
shr AH, 1
shr AL, 1
or [BX], AX
inc BX
inc BX
;5
mov AX, [BX]
shr AH, 1
shr AL, 1
or [BX], AX
inc BX
inc BX
;6
mov AX, [BX]
shr AH, 1
shr AL, 1
or [BX], AX
inc BX
inc BX
;7
mov AX, [BX]
shr AH, 1
shr AL, 1
or [BX], AX
; inc BX
; inc BX
;**
not__bold: ;======================
test CH, 80h
jz not__blink
mov BX, SI
;**BLINK
IFNDEF CLIPPER
;0
mov AX, [BX]
mov CL, 3
shr AL, CL
mov CL, 2
shr AH, CL
mov [BX], AX
inc BX
inc BX
;1
mov AX, [BX]
mov CL, 2
shr AL, CL
mov CL, 1
shr AH, CL
mov [BX], AX
inc BX
inc BX
;2
mov AX, [BX]
mov CL, 1
shr AL, CL
mov CL, 0
shr AH, CL
mov [BX], AX
inc BX
inc BX
;3
inc BX
inc BX
;4
mov AX, [BX]
mov CL, 0
shl AL, CL
mov CL, 1
shl AH, CL
mov [BX], AX
inc BX
inc BX
;5
mov AX, [BX]
mov CL, 1
shl AL, CL
mov CL, 2
shl AH, CL
mov [BX], AX
inc BX
inc BX
;6
; mov AX, [BX]
mov AX, [BX]
mov CL, 2
shl AL, CL
mov CL, 3
shl AH, CL
mov [BX], AX
; inc BX
; inc BX
;
ELSE
; Clipper – specjalne
mov AX, [SI]
not AX
mov [SI], AX
;
mov AX, [SI+12]
not AX
mov [SI+12], AX
; gdy ENH, to nie underl
jmp short not_underl
;
ENDIF
;**
not__blink: ;======================

;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
;not_blink_bold:
;————————————-*
mov CL, CH ; odtworzenie atrybutów
and CL, 77h
cmp CL, 01h ; underl
jne not_underl
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
; UNDERL
;6
mov AL, [SI+13]
not AL
mov [SI+13], AL
;
not_underl:
;————————————-*
mov CL, CH ; odtworzenie atrybutów
and CL, 77h
cmp CL, 70h
jne not_reversed
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
mov BX, SI
; REVERSE
;0
mov AX, [BX]
not AX
mov [BX], AX
inc BX
inc BX
;1
mov AX, [BX]
not AX
mov [BX], AX
inc BX
inc BX
;2
mov AX, [BX]
not AX
mov [BX], AX
inc BX
inc BX
;3
mov AX, [BX]
not AX
mov [BX], AX
inc BX
inc BX
;4
mov AX, [BX]
not AX
mov [BX], AX
inc BX
inc BX
;5
mov AX, [BX]
not AX
mov [BX], AX
inc BX
inc BX
;6
mov AX, [BX]
not AX
mov [BX], AX
; inc BX
; inc BX
;——————————–*
not_reversed:
test CH, 77h
jnz not_blank
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
mov BX, SI
; BLANK
sub AX, AX
;0
mov [BX], AX
inc BX
inc BX
;1
mov [BX], AX
inc BX
inc BX
;2
mov [BX], AX
inc BX
inc BX
;3
mov [BX], AX
inc BX
inc BX
;4
mov [BX], AX
inc BX
inc BX
;5
mov [BX], AX
inc BX
inc BX
;6
mov [BX], AX
; inc BX
; inc BX
not_blank:
;————————————-*
; ładowanie rejestru ES:DI
mov CL, row
mov AL, col
cbw
mov DI, AX
;
mov AX, 0b800h
mov ES, AX
;————————————-*
;
mov DX, 2000h ; dla przyśpieszenia wykonania
;
; DS:SI — display_buffer
;
;
row_0:
cmp CL, 0
jne row_1
mov BX, 0000h
jmp display_even
row_1:
cmp CL, 1
jne row_2
mov BX, 40f0h
jmp display_odd
row_2:
cmp CL, 2
jne row_3
mov BX, 0230h
jmp display_even
row_3:
cmp CL, 3
jne row_4
mov BX, 4320h
jmp display_odd
row_4:
cmp CL, 4
jne row_5
mov BX, 0460h
jmp display_even
row_5:
cmp CL, 5
jne row_6
mov BX, 4550h
jmp display_odd
row_6:
cmp CL, 6
jne row_7
mov BX, 0690h
jmp display_even
row_7:
cmp CL, 7
jne row_8
mov BX, 4780h
jmp display_odd
row_8:
cmp CL, 8
jne row_9
mov BX, 08c0h
jmp display_even
row_9:
cmp CL, 9
jne row_10
mov BX, 49b0h
jmp display_odd
row_10:
cmp CL, 10
jne row_11
mov BX, 0af0h
jmp display_even
row_11:
cmp CL, 11
jne row_12
mov BX, 4be0h
jmp display_odd
row_12:
cmp CL, 12
jne row_13
mov BX, 0d20h
jmp display_even
row_13:
cmp CL, 13
jne row_14
mov BX, 4e10h
jmp display_odd
row_14:
cmp CL, 14
jne row_15
mov BX, 0f50h
jmp display_even
row_15:
cmp CL, 15
jne row_16
mov BX, 5040h
jmp display_odd
row_16:
cmp CL, 16
jne row_17
mov BX, 1180h
jmp display_even
row_17:
cmp CL, 17
jne row_18
mov BX, 5270h
jmp display_odd
row_18:
cmp CL, 18
jne row_19
mov BX, 13b0h
jmp display_even
row_19:
cmp CL, 19
jne row_20
mov BX, 54a0h
jmp display_odd
row_20:
cmp CL, 20
jne row_21
mov BX, 15e0h
jmp display_even
row_21:
cmp CL, 21
jne row_22
mov BX, 56d0h
jmp display_odd
row_22:
cmp CL, 22
jne row_23
mov BX, 1810h
jmp display_even
row_23:
cmp CL, 23
jne row_24
mov BX, 5900h
jmp display_odd
row_24:
cmp CL, 24
jne row_25
mov BX, 1a40h
jmp display_even
row_25:
hRet
;=================================================================
; DI – col
; BX – współczynnik
; CX – 7fffh – dla przyśpieszenia wykonania
;=================================================================
display_even:
;
mov CX, 7fffh
;
lodsb ; [0]
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [1]
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [2]
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [3]
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [4]
add BX, 50h ;++
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [5]
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [6]
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [7]
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [8]
add BX, 50h ;++
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [9]
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [10]
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [11]
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [12]
add BX, 50h ;++
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [13]
mov ES:[BX+DI], AL
; add BX, DX
; and BX, CX
hRet
;=================================================================
display_odd:
;
mov CX, 7fffh
;
lodsb ; [0]
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [1]
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [2]
add BX, 50h ;++
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [3]
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [4]
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [5]
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [6]
add BX, 50h ;++
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [7]
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [8]
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [9]
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [10]
add BX, 50h ;++
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [11]
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [12]
mov ES:[BX+DI], AL
add BX, DX
and BX, CX
;
lodsb ; [13]
mov ES:[BX+DI], AL
; add BX, DX
; and BX, CX
hRet
;=================================================================
;
hRet
hEndp
;——————————————————————
hProc , , chr:BYTE
;
mov AH, 0Eh
mov AL, chr
mov BX, 0007h
INT 10h
;
hRet
hEndp
;——————————————————————
hProc , , cp:WORD
;
mov BX, WORD PTR cp
jmp SHORT fp_begin
fp_loop:
; INT 29h
push AX
CALL _fast_putchar
pop AX
fp_begin:
mov AL, BYTE PTR [BX]
inc BX
or AL, AL
jnz fp_loop
;
hRet
hEndp
;——————————————————————
; bajt b przekształca do postaci dziesiętnej, i wyświetla
hProc , , b:BYTE
;
sub AH, AH
mov AL, b
sub CX, CX ; licznik znaków
mov BX, 10 ; dzielnik
;
bt_getdigit:
sub DX, DX
div BX ; Remainder is last digit
add DL, ‚0’ ; to ASCII
push DX ; cyfra na stos
inc CX
or AX, AX ; czy już nic nie zostało
jnz bt_getdigit
;
; CL – ilość cyfr
;
bt_putdigit:
CALL _fast_putchar
pop AX ; cyfra ze stosu
; INT 29h
inc BX
loop bt_putdigit
;
hRet
hEndp
;——————————————————————
;——————————————————————
;═══════════════════════════════════════════════════════════════════════
;==================================================================

END

Reklamy
Ten wpis został opublikowany w kategorii Komputery i Internet i oznaczony tagami , , , , . Dodaj zakładkę do bezpośredniego odnośnika.

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj /  Zmień )

Zdjęcie na Google+

Komentujesz korzystając z konta Google+. Wyloguj /  Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj /  Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj /  Zmień )

Connecting to %s