B˜            „Player Protrackera w C!



ƒ[LeMUr/Fire & blabla]

„   Zrobiîem!‚  Tak,  mogë  z  caîâ  pewnoôciâ i dumâ zakrzyknâê "ZROBIÎEM!". Co
zrobiîem? Tytuî chyba wszystko wyjaônia...

ƒ      Uwaga na temat praw autorskich.
   Oto fragment úródîówki do playera (jest na dysku):

„___cut_here___

—;********************************************
—;* ----- Protracker V1.1B Playroutine ----- *
—;* Lars "Zap" Hamre/Amiga Freelancers 1991  *
—;* Bekkeliveien 10, N-2010 STRØMMEN, Norway *
—;********************************************

„___cut_here___

   Jak widaê autorem plajaîki jest Lars "Zap" Hamre. Nie znalazîem ani sîowa o
prawach autorskich, wiëc chyba moûna to traktowaê jako PD...

   Czas na maîy opis i równie maîe wyjaônienie. Player ten nie jest napisany w
C  (oczywiôcie),  a  w  asemblerze i jest (najprawdopodobniej) procedurâ Pubic
Domain.  Jest to standardowy grajek PT-CIAPlay rozpowszechniany z Protrackerem
1.1B,  wiëc  nie  powino  byê  bîëdów  z  odtwarzaniem  znanych  z  Amosa  czy
STReplay.library.  Po  dosîownie  zmienieniu  2 lub 3 komend (to, co zmieniîem
jest  widoczne  w  úródîówce)  nadaje  sië  do  uûycia  w C. Nie bëdë wnikaî z
szczegóîy  zmiany,  bo  sam  w asemblerze jestem zielony. Przerobiîem plajaîkë
uniwersalnâ metodâ - prób i bîëdów; dla zainteresowanych - obyîo sië bez Guru,
chociaû jako "moduî" czësto traktowana byîa pamiëê od 0xDFF000 (koderzy wiedzâ
co  to  znaczy)...  Teraz  mój  skromny  programik  testujâcy  odtwarza  moduî
znakomitego technika - Dreamera (moduî "Brocken Coin", chociaû to juû któryô z
kolei), a wszystko chodzi pewnie i nie "paôci sië" (hi Thufor! :).


ƒ   Jak  uûywaê  tego  produktu? ‚ Wszystko  macie  na dysku - w katalogu "Bonus
stuff".  Jest  tam  úródîówka  programu  testujâcego  oraz  objekt  gotowy  do
linkowania. Jak widaê w pliku Play.c jest taki oto fragment:

„___cut_here___

—extern void __asm STARTMODULE(register __a0 APTR memory);
—extern void __asm STOPMODULE(void);

„___cut_here___

Te  dwie  definicje  powodujâ,  ûe kompilator oczekuje funkcji STARTMODULE() i
STOPMODULE(),  które bëdâ doîâczone z innego pliku. To jest konieczne w kaûdym
programie korzystajâcym z tego plajera! Proszë o tym pamiëtaê. Obie procedurki
nie zwracajâ ûadnych danych, bo i po co? Czas na ich opis:

ƒ      StartModule()
   Procedura  wymaga  jednego parametru - adresu moduîu. Oczywiôcie moduî musi
byê  "ulokowany" w pamiëci Chip. Player nie dba o to, czy moduî jest moduîem i
czy  jest  to  moduî  Protrackera!  Musimy  byê  tego  pewni.  To samo dotyczy
rozpakowywania.  W sumie procedura ta nie robi nic poza zajëciem i odpowiednim
ustawieniem  przerwaï  CIA oraz rozpoczëciem odtwarzania moduîu. Reszta naleûy
do  nas  -  programistów.  Wydaje  mi  sië,  ûe jest to najlepsze rozwiâzanie.
Odtwarzanie  zawsze  zaczyna  sië od poczâtku. UWAGA - nie sâ zajmowane kanaîy
dúwiëkowe,  wiëc  próba  odtworzenia  innego  moda  innym  programem  moûe daê
nieoczekiwane  efekty  -  nie  zaleûy  to  ode  mnie,  moûe ktoô jest gotów to
poprawiê?

ƒ      StopModule()
   Nie  wymaga ûadnych parametrów. Powoduje oczywiôcie zatrzymanie odtwarzania
moduîu  (bez  bajerów  typu  "fade  out").  Po zatrzymaniu odtwarzania zwalnia
przerwanie  CIA,  ale  nie  zwalnia  pamiëci, wiëc moûna spokojnie "uruchomiê"
moduî jeszcze raz, oczywiôcie przez StartModule().

   Obie  te procedury sâ skompilowane pod Trash'M-One i zapisane jako plik dla
linkera  (komendâ  "WL").  Oznacza  to, ûe moûna spokojnie uûywaê tego pliku w
innych jëzykach kompilowanych, np. w C. Powinno to takûe dziaîaê w E i róûnych
Basicach  (nie  sprawdzaîem!)  -  wszystko  zaleûy  od tego, czy nasz ulubiony
kompilator  ma moûliwoôê doîâczania standardowych plików dla linkera. Na pewno
potrafi  to  Sas  C/C++  (powinno  dziaîaê na kaûdej wersji, sprawdzaîem tylko
6.55)  oraz  Aztec  C 5.0a (nie miaîem moûliwoôci sprawedzenia, ale wierzë, ûe
zadziaîa  :-)  i inne kompilatory C (Dice, GNU itp.). O ile w E jest moûliwoôê
(nie  wiem,  bo  nie  znam  E...)  doîâczenia  dowolnego  objektu  to na pewno
zadziaîa.  Z  Basicami  moûe  byê  róûnie,  ale  pod  Amosem to jest po prostu
przejebane! =)

   I  czas  na  obiecany  przykîad  wykorzystania  naszego  playera.  Oto plik
"Play.c":

„___cut_here___

—#include <exec/memory.h>
—#include <intuition/intuition.h>
—#include <proto/dos.h>
—#include <proto/exec.h>
—#include <proto/intuition.h>
—#include <stdio.h>
—#include <stdlib.h>

// delkaracje procedur odtwarzajâcych
—extern void __asm STARTMODULE(register __a0 UBYTE *memory);
—extern void __asm STOPMODULE(void);

// zmienne obsîugujâce pamiëê
—APTR Bufor=NULL;
—ULONG Size=NULL;

// okno i intuition.library
—struct IntuitionBase *IntuitionBase=NULL;
—struct Window *Okno=NULL;
—struct NewWindow mywin=
—{
—   0, 11,
—   250, 11,
—   NULL, NULL,
—   CLOSEWINDOW,
—   WINDOWCLOSE | WINDOWDEPTH | WINDOWDRAG | ACTIVATE | NOCAREREFRESH,
—   NULL, NULL,
—   "Protracker 1.1B player!",
—   NULL, NULL,
—   NULL, NULL,
—   NULL, NULL,
—   WBENCHSCREEN
—};


—void out(int kod)
// Procedura zwalnia co byîo zajëte i wychodzi z podanym kodem bîëdu
// (dostëpny np. poprzez "SET" z CLI).
—{
—   if(Okno)
—      CloseWindow(Okno);

—   if(Bufor)
—      FreeMem(Bufor, Size);

—   if(IntuitionBase)
—      CloseLibrary((struct Library *)IntuitionBase);

—   exit(kod);
—}


—void main(int argc, char *argv[])
// Caîy program
—{
—   BPTR file, lock;
—   struct FileInfoBlock __aligned fib;

—   if(argc!=2)
—   {
—      printf("I need one argument - a module name!\n");
—      out(100);
—   }

   // biblioteka...
—   if(!(IntuitionBase=(struct IntuitionBase *)
—            OpenLibrary("intuition.library",34L)))
—      out(10);

   // okno...
—   if(!(Okno=OpenWindow(&mywin)))
—      out(20);

   // plik...
—   if(!(lock=Lock(argv[1], ACCESS_READ)))
—   {
—      printf("Unable to lock \"%s\"\n", argv[1]);
—      out(25);
—   }

—   if(!Examine(lock, &fib))
—   {
—      printf("Unable to examine \"%s\"\n", argv[1]);
—      UnLock(lock);
—      out(30);
—   }

—   if(!(Size=fib.fib_Size))
—   {
—      printf("File couldn't be 0 bytes long!\n");
—      UnLock(lock);
—      out(32);
—   }

—   if(!(Bufor=AllocMem(Size, MEMF_CHIP | MEMF_CLEAR)))
—   {
—      printf("Unable to allocate memory!\n");
—      UnLock(lock);
—      out(35);
—   }

—   if(!(file=Open(argv[1], MODE_OLDFILE)))
—   {
—      printf("Unable to open file \"%s\"\n", argv[1]);
—      UnLock(lock);
—      out(40);
—   }

—   Read(file, Bufor, Size);
—   Close(file);
—   UnLock(lock);

   // gramy!
—   printf("And... let's play!\n");
—   STARTMODULE(Bufor);

   // pëtla obsîugujâca CloseWindow
—   for(;;)
—   {
—      struct IntuiMessage *imsg;
—      ULONG   clas;

—      WaitPort(Okno->UserPort);

—      imsg=(struct IntuiMessage *)GetMsg(Okno->UserPort);
—      clas=imsg->Class;

—      ReplyMsg((struct Message *)imsg);

—      if(clas==CLOSEWINDOW)
—      {
         // wyjscie - zatrzymanie moduîu
—         printf("Quit it! Quit it!!!\n");
—         STOPMODULE();
—         out(0);
—      }
—   }
—}

„___cut_here___


   Myslë,  ûe  komentarze  sâ zbëdne. Jeôli czegoô nie rozumiecie to wystarczy
poszukaê  w  innych  moich  (i  nie  tylko)  artykuîach  traktujâcych  o  C  i
Kickstarcie.  Mam  nadziejë,  ûe na coô moja praca sië przydaîa (nie byîa moûe
wielka, ale biorâc pod uwagâ mojâ prawie ûadnâ znajomoôê asemblera...) i teraz
odtwarzanie moduîów nie bëdzie udrëkâ nawet w C! Czego sobie i Wam ûyczë.

„                                               LeMUr‚/ƒ Fire
                                                   ‚/ƒ& blabla
