Metropoli BBS
VIEWER: loader.pas MODE: TEXT (CP437)
{.mod loader}
{$i-}
{$I load_inc.pas}

procedure pokeb(offset:longint; value:byte);
var page:word;
    offs:word;
begin
 page:=(longint(offset) shr 14);
 offs:=offset and $3FFF;
 if ems.page<>page then begin
  map_page(ems.handle,0,page);
  ems.page:=page;
 end;
 mem[ems.addr:offs]:=value;
end;

procedure free_mod;
var i:word;
begin
{ for i:=1 to module.instruments do if (samples[i].used) and (samples[i].data<>nil)
  then freemem(samples[i].data,samples[i].length);}
 free_ems(ems.handle);
 for i:=0 to song.patterns do if song.pattern[i]<>nil then
  freemem(song.pattern[i],5*64*module.channels+10);
end;

function load_mod(name:string):boolean;
var f:file;
    sig:string[4];

function getname:string;
var str:string[20];
    b:byte;
begin
 seek(f,0);
 blockread(f,str[1],20);
 str[0]:=#20;
 for b:=20 downto 1 do if str[b]=#0 then str[0]:=char(b-1);
 getname:=str;
end;

function amigaword(w:word):word; assembler;
asm
 mov al,[w].byte[1];
 mov ah,[w].byte[0];
end;

function getsampleinfo:boolean;
var i:byte;
    w:word;
    b:byte;
begin
 getsampleinfo:=true;
 seek(f,20);
 for i:=1 to module.instruments do with samples[i] do begin
  blockread(f,name[1],22);
  name[0]:=#22;
  for b:=22 downto 1 do if name[b]=#0 then name[0]:=char(b-1);
  blockread(f,w,2);
  length:=longint(amigaword(w))*2;
  inc(totalsamples,length);
  blockread(f,b,1);
  if b<16 then c2spd:=finetunes[b] else c2spd:=8363;
  blockread(f,volume,1);
  blockread(f,w,2);
  loop.start:=longint(amigaword(w))*2;
  blockread(f,w,2);
  loop.length:=longint(amigaword(w))*2;
  if loop.length<3 then begin loop.length:=0; loop.start:=0; end;
  loop.endi:=loop.start+loop.length;
  used:=(length<>0);
 end;
end;

function loadpatterns:boolean;
var i:byte;
    a:word;
    b0,b1,b2,b3:byte;
    p:pointer;
    offs:word;

function getnote(amigaval:word):byte;
var c2:byte;
begin
{getnote:=$ffff;
for c2:=1 to 36 do
 if (amigaval>periods[c2]-2) and (amigaval<periods[c2]+2)
  then getnote:=c2;}
getnote:=$ff;
for c2:=0 to 107 do
 if amigaval>=periods[c2+24] then begin
  getnote:=c2;
  exit;
 end;
end;

var periodfreq:word;
begin
 loadpatterns:=true;
 write('reading patterns..');
 getmem(p,64*module.channels*4);
 for i:=0 to song.patterns do begin
  getmem(song.pattern[i],5*64*module.channels+10);
  blockread(f,p^,64*module.channels*4);
  offs:=0;
  for a:=1 to 64*module.channels do begin
   b0:=mem[seg(p^):ofs(p^)+offs];
   b1:=mem[seg(p^):ofs(p^)+offs+1];
   b2:=mem[seg(p^):ofs(p^)+offs+2];
   b3:=mem[seg(p^):ofs(p^)+offs+3];
   inc(offs,4);
{   blockread(f,b0,1);
   blockread(f,b1,1);
   blockread(f,b2,1);
   blockread(f,b3,1);}

   mem[seg(song.pattern[i]^):ofs(song.pattern[i]^)+a*5]:=(b0 and $F0)+(b2 shr 4);
   periodfreq:=word(word(b0 and $0F) shl 8)+word(b1);
   mem[seg(song.pattern[i]^):ofs(song.pattern[i]^)+a*5+1]:=getnote(periodfreq);
   mem[seg(song.pattern[i]^):ofs(song.pattern[i]^)+a*5+2]:=b2 and $0F;
   mem[seg(song.pattern[i]^):ofs(song.pattern[i]^)+a*5+3]:=b3;
   mem[seg(song.pattern[i]^):ofs(song.pattern[i]^)+a*5+4]:=255; {volume, impossible value}
  end;
 end;
 freemem(p,64*module.channels*4);
 writeln('done!');
end;

function readsamples:boolean;
var a,posi:longint;
    i:byte;
    pos:longint;
    get:longint;
 {   koe:byte;}
    buf:pointer;
   {$ifdef ripsamples}
    outf:file;
   {$endif}
    ch:char;
const disk=4096;
begin
 writeln('sampleja yhteensä ',totalsamples,' tavua.');
 writeln('filussa sampleja  ',filesize(f)-(1084+longint(module.channels)*4*64*longint(song.patterns+1)),' tavua.');
 write('reading samples..');
 seek(f,1084+longint(module.channels)*4*64*longint(song.patterns+1));
{$ifdef purkka}
 seek(f,filesize(f)-totalsamples);
{$endif}
 readsamples:=true;
 getmem(buf,disk);
 for i:=1 to module.instruments do if samples[i].length>0 then begin
 {$ifdef ripsamples}
 assign(outf,'SAM!'+strr(i)+'.RAW');
 rewrite(outf,1);
 {$endif}
{  a:=samples[i].length;
  if a>64000 then begin
   a:=64000;
   writeln('sample #',i,' too big; max size is 64000 bytes.');
  end;
  getmem(samples[i].data,a);
  blockread(f,samples[i].data^,a);
  seek(f,filepos(f)+(samples[i].length-a));}
  a:=samples[i].length;
  posi:=0;
  samples[i].data:=ems.used;

  inc(ems.used,samples[i].length);

  repeat
   if a>disk then get:=disk else get:=a;
   dec(a,get);
   blockread(f,buf^,get);
   if ioresult<>0 then begin
    writeln('hih, sample nro ',i,' bugaa; ',samples[i].length,' byteä, joista ',a,' lukematta');
    writeln(filepos(f),'/',filesize(f));
    ch:=readkey;
   end;
   {$ifdef ripsamples}
   blockwrite(outf,buf^,get);
   {$endif}
   for pos:=0 to get-1 do
    pokeb(samples[i].data+posi+pos,mem[seg(buf^):ofs(buf^)+pos]);
   inc(posi,get);
  until a=0;
  {$ifdef ripsamples}
  close(outf);
  {$endif}
 end;
 freemem(buf,disk);
 writeln;
 writeln('done!');
end;

function loadsong:boolean;
var b:byte;
    sig:string[4];
begin
 loadsong:=true;
 seek(f,950);
 blockread(f,song.length,1);
 writeln('song length  : ',song.length);
 blockread(f,b,1);
 writeln('dummy byte: ',b,' (usually 127)');
 writeln;
 song.patterns:=0;
 for b:=1 to 128 do begin
  blockread(f,song.order[b],1);
  if (song.order[b]>song.patterns) and (b<=song.length) then
   song.patterns:=song.order[b];
 end;
 writeln('phys patterns: ',song.patterns+1);
 if filepos(f)<>1080 then writeln('**** BUGIIIIIII!!!! ****',#7#7);
 blockread(f,sig[1],4);
 sig[0]:=#4;
 writeln('module type  : ',sig);
 if not(loadpatterns) then loadsong:=false;
 if not(readsamples) then loadsong:=false;
end;

function check_mk:boolean;
var code:integer;
begin
 check_mk:=true;
 seek(f,1080);
 module.instruments:=31;
 blockread(f,sig[1],4); sig[0]:=#4;
 if ((sig='M.K.') or (sig='M!K!')) then module.channels:=4
 else
  if (sig='OCTA') then module.channels:=8
  else
   if (pos('CH',sig)=3) then begin
    val(copy(sig,1,2),module.channels,code);
    check_mk:=code=0;
   end
   else
    if pos('CHN',sig)=2 then begin
     val(copy(sig,1,1),module.channels,code);
     check_mk:=code=0;
    end
    else
     if pos('FLT',sig)=1 then begin
      val(copy(sig,4,1),module.channels,code);
      check_mk:=code=0;
     end
     else
      if pos('TDZ',sig)=1 then begin
       val(copy(sig,4,1),module.channels,code);
       check_mk:=code=0;
      end
      else check_mk:=false;
end;

begin
 load_mod:=false;
 if not(ems_installed) then begin
  writeln('no ems.');
  exit;
 end;
 assign(f,name);
 reset(f,1);
 if ioresult<>0 then begin
   if pos('.',name)<>length(name)-3 then name:=name+'.MOD';
  assign(f,name);
  reset(f,1);
 end;
 if ioresult<>0 then begin
  writeln('file not found');
  exit;
 end;
 writeln('loading module: ',name);
 if not(check_mk) then begin
  close(f);
  writeln('not a (31-instrument) mod.');
  exit;
 end;
 module.title:=getname;
 module.maxsamples:=32;
 song.speed:=6;
 song.bpm:=125;

 master:=64;
 writeln;
 writeln('module name   : ',module.title);
 writeln('channels      : ',module.channels);
 writeln;
 totalsamples:=0;
 if not(getsampleinfo) then begin
  writeln('error.');
  exit;
 end;
 if totalsamples>(longint(free_pages)*16384) then begin
  close(f);
  writeln('out of memory.');
  exit;
 end;
 ems.used:=0;
 ems.handle:=alloc_pages((totalsamples+16383) div 16384);
 map_page(ems.handle,0,0);
 ems.page:=0;
 ems.addr:=ems_addr;
 if not(loadsong) then begin
  writeln('error.');
  close(f);
  exit;
 end;

 writeln(filepos(f),'/',filesize(f));
 close(f);
 load_mod:=true;
{ writeln('press any key.');
 readkey;}
end;
[ RETURN TO DIRECTORY ]