You are on page 1of 6

Tematem tego wydania kursu jest InertiaPlayer & ProTracker.

Na początek trochę historii, czyli jak doszło do


powstania Inertii, a potem ProTrackera.

Wszystko zaczęło się od wydania przez Mirage pakietu z playerem plików MD8. Były to zmodyfikowane pliki MOD,
tzn. sample 8-bitowe przekonwertowane na 4-bit, oraz zmiany w trackach itp. Wszystie te zmiany miały przyspieszyć
odgrywanie i skrócić rozmiar w stosunku do oryginalnego pliku MOD. Zaowocowało to wzrostem zużytych dyskietek
5i1/4 i niemożnością pochwalenia się swoją twórczością przed użytkownikami Amig, PC, ST. Profi jako zapalony
muzykant, dotąd tylko CMC, później MPT zapragnął nie tylko dokonywać konwersji MOD->MD8, ale stworzyć w
końcu coś swojego.

Sam engin playera, sposób regulacji głośności sampla, schemat odczyty pliku MD8 otrzymaliśmy od Marka
Goderskiego, autora opisu systemu SpartaDosX. Ten bardzo ciekawski człowiek postawił sobie za cel disasemblacje
playera i przyjrzenia mu się z bliska. Sam program był zabezpieczony, ładował się w niskie obszary normalnie
nachodząc na DOS, dodatkowo był eorowany kilka razy. Autorom bardzo zależało by nikt nie zajrzał do źródełka ;).
Dzięki odpowiedniej wersji Sparty, zostawiającej dużo miejsca dla programów, swoich disasemblerów i innych
narzędzi pod Sparte, udało się Markowi zdisasemblować player i zrozumieć jego działanie. Tak wyedukowani przez
niego i wzbogaceni źródełkami w formacie jedynie słusznym czyli QA (obecnie X-Asm), zaczęliśmy tworzyć Inertie,
tzn. Profi zaczął tworzyć, potem doszła niezdrowa konkurencja z mojej strony, tzn. jak on stworzył wersje np. X, to ja
coś poprawiałem i wychodziła wersja Y. Podobnie było w przypadku Visage, on zaczął, ale że nie miał procedur
kompresji, dekompresji to ja skończyłem. Może dlatego Profi potem odwrócił się od Madtemu, a może to przez
dziewczynę.

Wracając do tematu, mieliśmy playera co prawdza tylko MD8, ale nie było jeszcze 8-bitowego przetwornika. Na
horyzoncie pojawił się jednak Psychol, który oprócz masy innych wynalazków militarnych jak żelazko rozpylające gaz
wpadł na pomysł zwiększenia możliwości dźwiękowych Atarka przez 8-bitowy przetwornik. Ekipa Madteamu zebrała
się w ciemnym pokoiku Psychola, by usłyszeć nową zabawkę. Na początku był tylko 1 kanał. Psychol napisał sobie
program do odtwarzania sampli, by potem męczyć sąsiadów telefonami i odtwarzanymi z Atari dziwnymi tekstami.
Zrobił też automatyczną sekretarkę, która odtwarzała nagrany tekst, a potem zapisywala ileś KB rozmowy.

Pojawiły się inne pomysły na zastosowanie wynalazku, w tym czasie mieliśmy już źródła playera MD8, wiedzieliśmy
że tak naprawdę gra on na jednym kanale, wartość wpisywana do rejestru była wyliczana jako suma wszystkich
kanałów. Taki sposób miał wyeliminować zagłuszanie się jednego kanału przez drugi (pewnie chodzi o interferencje).
Profi wziął się z zapałem do pracy i tak narodziła się późniejsza Inertia. Aktualnie wczytywała jeszcze MD8 ale
odtwarzała już na 8-bitowym przetworniku, jakby go nazwać ... Covoxie ;) Efekt odgrywania sumy 4 kanałów na 1
przetworniku był mało zadowalający, były duże zniekształcenia, zbyt wyraźnie było to słychać. Tak więc żeby dużo nie
kombinować trzeba dorzucić następne 3 kanały. I tak dzięki współpracy Psychola i Profiego zaczął wyłaniać się coraz
to bardziej dopracowany kształt playera. Pojawiły się też sugestie aby przyspieszyć player przez sprzętową regulacje
głośności, ale Psychol stwierdził, że skomplikowałoby to zbytnio całego Atarowskiego Covoxa. Tak więc pozostaliśmy
przy metodzie zastosowanej w MD8, odpowiednio tylko modyfikując tablice głośności, ze wzoru którego już nie
pamiętam.

Natomiast ProTracker był naturalnym rozwinięciem Inertii, który miał zaspokoić ambicje twórcze Profiego. Był to
największy jego projekt, projekt jak najbardziej udany i skończony. Przedtem był jeszcze nigdy nie pokazany ogółowi
sampler i odtwarzacz sampli w zbajerowanym przez Rockego środowisku graficznym, z graficznym equilizerem, z
zaznaczaniem fragmentów sampla i wszystkich z tym związanych bajerów.

Inertia Player v3.7

Nie jest to wersja Inertii Profiego, ale nie powinna się wiele różnić od jego wersji 3.7 (może kiedyś zdarzy się cud,
Profi zajrzy tutaj i dorzuci coś do tego ogródka). Operacje I/O ze stacją dysków odbywają się bez udziału DOSu. Tak
więc Pinokiowi się to nie spodoba ;)

Tak jak w przypadku ProTrackera jeśli ktoś będzie chciał cokolwiek modyfikować, niech to będzie zorganizowane.
Jeden człowiek, czy grupa czuwa nad projektem, inni pomagają. Żeby nie było tak, że nagle pojawi się 100 wersji
różniących się autorem ;)

Pare ogólnych uwag na temat działania. Dla przyspieszenia działania playera jest on umieszczony na stronie 0. Całość
w sumie zajmuje 3 strony pamięci, od $0000-$02ff i nie ma wpływu na stos, stos jest nieużywany, ponieważ wyłączone
są wszelkie przerwania. Normalnie kod playera umieszczony jest gdzieś w pamięci i dopiero gdy jest potrzebny
przepisywany jest na strone 0 i dalej. Oczywiście zawartość strony 0 musi zostać zachowana, a po skończeniu
odgrywania jest odtwarzana jej zawartość.

W celu przyspieszenia odgrywania sampli, sprawdzany jest tylko starszy bajt ich adresu. Sposób ten wymaga aby
sample były odpowiednio umieszczone w pamięci, tzn. młodszy bajt adresu ostatniego bajtu sampla jest równy 0. Jak
to osiągngąć? Długość sampla jest reprezentowana przez liczbe stron, tzn. dla długości sampla $1578 mamy $15+1
stron. W jednym banku pamięci zmieścimy $40 stron. Najwięcej stron zmieścimy w pamięci głównej, będzie tutaj
najdłuższy z sampli. Jeśli będziemy korzystali z DOSu tej pamięci będzie mniej.
Podczas odtwarzania sampli wyłączone są wszystkie przerwania. Synchronizacja odbywa się przez wywołanie
procedury odgrywającej sample N razy. Ta procedura znajduje się właśnie na stronie zerowej pamięci. Potem następuje
skok do procedury odczytującej pattern, modyfikacja adresów w playerze i znowu skok na strone zerową. Player za
każdym razem kiedy wpisuje wartości do 4 kanałów musi zajmować tyle samo cykli zegara. Im dokładniej będzie to
zrealizowane tym lepszej jakości otrzymamy dźwięk. Dokładniej częstotliwość odtwarzania mierzył Psychol
oscyloskopem i jakimś swoim elektronicznym urządzeniem. Zliczało ono odwołania do strony pamięci z rejestrami
Covoxa.

Przykład odtworzenia sampla na 1 kanale w playerze Inertia. Pętla ma stałą długość deklarowaną w stałej VBL, tutaj
$d8 i ma ona wpływ na tempo. Jakakolwiek zmiana w playerze, zmieniająca liczbe cykli spowoduje zmianę tej
wartości.

pmain equ *

bank0 lda #$fe ;bank w którym znajduje się sampl


sta $d301

ist_0 lda #0 ;tego nie rozumiem, bo brak w playerze odwolan do ist_0 itp.
iad0_m adc #0 ;ale sa odwołania do "iad0_m" i "iad0_s"
sta ist_0+1

lda p_0c+1 ;modyfikacja adresu sampla, dodajemy wartosc z tablicy czestotliwosci


iad0_s adc #0 ;mlodszy bajt adresu
sta p_0c+1
bcc p_0c
inc p_0c+2 ;starszy bajt adresu
lda p_0c+2 ;sprawdzenie czy to już koniec sampla
ien0_s cmp #0
bcc p_0c

ire0_m lda #0 ;ustawienie nowego adresu poczatkowego sampla


sta p_0c+1 ;czyli petla sampla
ire0_s lda #0
sta p_0c+2
jmp bank1

p_0c ldx $ffff ;wartość sampla


ivol10 lda $d800,x ;tablica głośności
ch0 sta $d600 ;graj, jeśli urzadzeniem jest POKEY to będzie adres $d200

bank1 ........... nastepny kanal itd.

Na końcu tej pętli występuje już tylko:

p_e dey ;zmniejszamy wartość Y i pętlimy się dalej


beq pat
jmp pmain

* -----------------
* requests

pat ldy #vbl ;odświeżamy zawartość rejestru Y


dec cnts ;licznik długości patternu
beq pre
jmp pmain

pre lda #0 ;tutaj zaczyna się procedura dekodowania patternu


sta patend
lda #$fe
sta $d301

*---------------------------
* track 0

Normalnie w pliku ASM wygląda to inaczej ponieważ wszyskie rozkazy "lda" "sta" "inc" musiały zostać zapisane w
formie "dta b(lda),b(value)", dlaczego? Spójrzmy na taki przykład:

org $0000
lda bajt
bajt dta b(0,1,2,3,4,5)

Po kompilacji otrzymamy:
X-Assembler 2.5.2 by Fox/Taquart
Source: G:\!Atari\inne\_profi\it37\xxx.asm
1 opt h+
2 org $0000
3
4 0000 main
5 FFFF> 0000-000B> AD 06 + lda bajt ;rozkaz $AD nie dotyczy strony zerowej
6 0003 AE 07 00 ldx bajt+1 ;tutaj też zamiast na 2-óch bajtów mamy 3-y
7
8 0006 00 01 02 03 04 05 bajt dta b(0,1,2,3,4,5)

Dopiero jeśli tablica "bajt" wystąpiłaby przed programem, kompilator skompilowałby to z rozkazami strony zerowej.

X-Assembler 2.5.2 by Fox/Taquart


Source: G:\!Atari\inne\_profi\it37\xxx.asm
1 opt h+
2 org $0000
3
4 FFFF> 0000-0009> 00 01 + bajt dta b(0,1,2,3,4,5)
5
6 0006 main
7 0006 A5 00 lda bajt ;mamy 2-bajty
8 0008 A6 01 ldx bajt+1 ;tutaj też czyli to musi dotyczyć strony zerowej
9

Uruchomienie Inertii, kompilacja pliku "IT37.ASM":


opt h+
org $8000 ;załadowanie tablic głośności
ins 'mod8.tab'

org $7000 ;załadowanie skompliowanego playera


ins 'play37.obx'
org $2000 ;załadowanie skompilowanej Inertii
ins 'mod37.obx'

org $600

start ldx #18


ldy #0
s lda $2000,y ;przepisanie Inertii pod adres $0700
d sta $0700,y
dey
bne s
inc s+2
inc d+2
dex
bne s
jmp $0700 ;i uruchomienie
run start

Uruchamiamy plik "IT37.OBX" i możemy już używać Inertii. W przypadku emulatora wystarczy że w napędzie 1
będzie dyskietka z plikami MOD, a program możemy uruchomić przez "ALT+X".

ProTracker v1.5

Dysponuje tylko kopią v1.5, nie jestem pewien czy były nowsze, wiem że w stosunku do Inertii player ma niższą
częstotliwość odtwarzania oraz mniej efektów. Ostatnia z Inertii miała coś więcej niż 3 komendy występujące w
ProTrackerze. Aktualnie przyglądając się kodowi programu można zauważyć że w QA zabrakło miejsca na etykiety i
większość skoków Profi zapisywał w postaci "*+nn", co nie sprzyja przejrzystości programu. Jakiekolwiek
modyfikacja muszą być przeprowadzane ostrożnie, ale są możliwe bo Profi nie optymalizował zbytnio trackera.

Oczywiście jeśli ktokolwiek będzie coś poprawiał powinien udostępnić to ogółowi i powinno to być ujednolicone, tzn.
jest jedna osoba która wprowadza modyfikacje, czyli czuwa nad projektem, a nie kildadziesiąt poprawia i kilkadziesiąt
wersji się pojawia. Większość osób jest już dorosłych więc nie powinno być problemów ze zrozumieniem tej zasady.

Pierwsza modyfikacja dotyczy procedur zmiany oktawy. Widać że zaremowane znakiem ";" instrukcje w podprogramie
"_dn" powtarzają się w podprogramie "_up". Dzięki takiej optymalizacji zwolniliśmy troche pamięci.

_up lda okt ;podnies oktawe 1 wyzej


cmp #2
beq _up1
inc okt
inc okt
_oktShow ldx okt
lda oktawa,x
sta _e1+9
inx
lda oktawa,x
sta _e1+10
inx
lda oktawa,x
sta _e1+11
jsr _pr
_up1 jsr cl_k
rts

_dn lda okt ;opusc oktawe nizej


beq _up1
dec okt
dec okt

; ldx okt
; lda oktawa,x
; sta _e1+9
; inx
; lda oktawa,x
; sta _e1+10
; inx
; lda oktawa,x
; sta _e1+11
; jsr _pr
; jsr cl_k
; rts
jmp _oktShow

"_e1+9" "_e1+10" "_e1+11" to adresy pamięci obrazu, czyli miejsca w których pojawiają się napisy reprezentujące
oktawe, np. "1:2" "2:3"

Poniższa modyfikacja optymalizuje szybkość działania, oszczędzamy 2 cykle zegara.

Oryginalnie wyglądało to tak:

_p0rom ldx #0
_pp1 lda TempBuffer,x
tay

A po modyfikacji tak:
_p0rom ldx #0 _pp1
ldy TempBuffer,x
; tay
lda ZeroPage,x
sta TempBuffer,x
tya
sta ZeroPage,x
inx
cpx #$d8
bne _pp1
rts

Zadaniem tej procedury jest przed każdym odegraniem czegokolwiek przepisanie procedur znajdujących się w
"TempBuffer" na stronę zerową, a dane znajdujące się na stronie zerowej przepisać do "TempBuffer". Te procedury to
skompilowany player, w sumie $d8 bajtów.

Podobnie można postępować w przypadku pozostałych procedur, np. główna rozdzielnia obsługująca klawisze
"KEYBD". Oto jej fragment:
keybd jsr wait
lda 764
cmp #231
bne *+5
jmp _exit ;opusc program
cmp #173
bne *+5
jmp _trans ;transpozycja
cmp #150
bne *+5
jmp _exchg ;zmiana instrumentu
cmp #71
bne *+5
jmp inc_p ;zwieksz nr. patternu
cmp #70
bne *+5
jmp dec_p ;zmniejsz nr.patternu
cmp #15
bne *+5
jmp dn_p ;przes. w dol patt.
cmp #14
bne *+5
...
...
...
itd.

Można przyspieszyć działanie kosztem pamięci, np. kosztem 512 bajtów, pierwsze 256 bajtów to młodsze adresy
procedur, ostatnie 256 bajtów to starsze adresy procedur. Numer określający kod naciśniętego klawisza z 764 byłby
indeksem do naszej tablicy. Bierzemy młodszy, starszy modyfikujemy adres w pamięci i JMP, np.

Sposób najszybszy:

keybd jsr wait


ldy 764
lda lAdr,y ;4 cykle
sta _jmpAdr+1 ;4
lda hAdr,y ;4
sta _jmpAdr+2 ;4
_jmpAdr jmp $ffff ;3
;Razem 15 cykli

Sposób zajmujący więcej cykli zegara, ale najkrótszy. Adresy w tablicy muszą być zmniejszone o 1. Wykorzystana jest
właściwośc instrukcji "RTS", która zdejmuje ze stosu pomniejszony o 1 adres powrotny i tam skacze.

keybd jsr wait


ldy 764
lda hAdr,y ;4 cykle
pha ;3
lda lAdr,y ;4
pha ;3
rts ;6
;Razem 20 cykli

Uwaga: Niektóre obszary są deklarowane na "sztywno". Należy dokładnie zapoznać się z mapą pamięci jaką
wykorzystuje ProTracker zanim zaczniemy jakieś drastyczne zmiany. W pliku "ADRESY.ASM" znajdują się
deklaracje etykiet.

Pierwsze zmiany jakie bym proponował to zamiana skokow "*+nn" na odpowiadające im etykiety.

Główne procedury:

_VOLMV procedura wywoływana jest przed odegraniem całego MOD-a lub patternu. Przepisuje tablice
głośności z ostatniego banku pamięci (spod adresu $4000 pod adres $d800 32-strony pamięci, ostatnią stronę
powiela $f700 na $f800).
LOA_MOD procedura wczytująca plik MOD, patterny pod $c600, nagłówek pliku MOD to 1084 bajty
PMAIN integralna część playera, tutaj następuje dekodowanie patternu dla każdego tracka i modyfikacja
adresów playera.
IO operacje wejścia/wyjścia
FUNC2 procedury odczytu sampla z nagłówkiem 27-bajtowym
ORDERS procedury obsługi edycji okna "ORDER"
XCHG procedury obsługi "wymiany instrumentu na inny"
TRANS procedury obsługi "transpozycji"
FUNCTION pozostałe procedury związane z edycja tracku, patternu itp.
MOVE przepisuje tablice głośności do ostatniego banku pamięci, jeśli wybrane urządzenie to POKEY to
modyfikuje tablice, jeśli COVOX to modyfikuje program i zamiast "lsr @" wstawia rozkazy "nop" wtedy tablica
nie zostaje zmodyfikowana. Tablice "TIDL" oraz "TID2" zostają przepisane odpowiedio pod "AdrTidl" oraz
"AdrTid2".
TIDL tablice nut - częstotliwosci dla sampli, wartość z tablicy dodawana jest do adresu sampla
TID2 tablica nut uzywana podczas edycji do odtwarzania pojedyńczych sampli
SELECT stąd startuje cały program, rozpoznanie pamięci dodatkowej, wybór urządzenia Pokey lub Covox

Główne pliki:

TS.FNT zestaw znaków dla ProTrackera, ładowane pod adres $2000


VOLUME.TAB tablica głośności, ładowana pod adres $8800
PM.ASM źródło playera, w osobnym pliku bo nie można załadować bezpośrednio do pamięci czegokowiek tak
długiego na strone 0.

Sposób kompilacji głównego pliku TR.ASM:

Najpierw kompilujemy plik "_PMAIN.ASM" bez nagłówka (opt h-). Powstały plik "_PMAIN.OBX" zostanie
wykorzystane podczas kompilacji "TR.ASM"
Kompliujemy plik "TR.ASM". Na samym początku występuje kompilacja pliku "PM.ASM" bez generowania
nagłówka i pliku wynikowego "opt h-o-". Jest to konieczny zabieg, który umożliwia pozostałej części programu
poznanie adresów występujących w playerze. Odwołania do nich będą kompilowane jako odwołania do strony
zerowej. Plik "_PMAIN.OBX" to tak naprawde skompilowany plik "PM.ASM".

You might also like