Metropoli BBS
VIEWER: example.c MODE: TEXT (ASCII)
#define INCL_DOSFILEMGR
#define INCL_DOSDEVICES
#define INCL_DOSPROCESS
#include <os2.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "struct.h"
#include "ultradev.h"
#include "s3mload.h"

SAMPINFO *Samples; 
HFILE GUSHandle, modin;

APIRET SampleMemFree(void);

static S3MHEADER header;
static unsigned char PatternOrder[256];
static SCREAMSAMPLE s;

int main(int argc, char *argv[])
{
 ULONG Wrote, Action;
 int i, j, lo, temprep, hdr;
 short int *paraptr;
 char *SampMem;   /* tijdelijke buffer om samples naar GUS te sturen */
 SAMPINFO *SampInfo;
 int foffset;	//offset sample inside s3m file
 APIRET rc;
 
 Action = 2;
 
 if(argc != 2) return(FALSE);

 rc = DosOpen(argv[1],     /* file name from Open dialog */
		  &modin,	      /* file handle returned */
		  &Action,
		  0L,
		  FILE_NORMAL,
		  OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
		  OPEN_FLAGS_SEQUENTIAL | OPEN_ACCESS_READONLY | OPEN_SHARE_DENYWRITE,
		  (PEAOP2)NULL);
 ON_ERROR(rc, S3MTestAndLoad_Err);

 DosSetFilePtr(modin, 0, FILE_BEGIN, &Wrote);
 rc = DosRead(modin, &header, sizeof(S3MHEADER), &Wrote);
 ON_ERROR(rc, S3MTestAndLoad_Err);

 rc = memcmp(header.scrm, "SCRM", 4);
 if(rc) return(2);

 rc = DosAllocMem(&Samples, (header.insnum+1)*sizeof(SAMPINFO), PAG_COMMIT | PAG_WRITE);
 ON_ERROR(rc, S3MTestAndLoad_Err);

 DosSetFilePtr(modin, 0x60, FILE_BEGIN, &Wrote);
 //bepaal song lengte
 rc = DosRead(modin, &PatternOrder, header.ordnum, &Wrote);
 ON_ERROR(rc, S3MTestAndLoad_Err);
 
 //reserveer geheugen voor paraptrs naar instruments + patterns
 rc = DosAllocMem(&paraptr, 2*(header.patnum + header.insnum), PAG_COMMIT | PAG_WRITE);
 ON_ERROR(rc, S3MTestAndLoad_Err);

 rc = DosRead(modin, paraptr, 2*(header.patnum + header.insnum), &Wrote);
 ON_ERROR(rc, S3MTestAndLoad_Err);

 InitDevice();
  
 /* Samples oversturen naar de GUS
    Aanname: Samples =< 128K */

 rc = DosAllocMem(&SampMem, (128*1024), PAG_COMMIT | PAG_WRITE);
 ON_ERROR(rc, S3MTestAndLoad_Err);

  //plus een voor null sample
  SampInfo = Samples + 1;

  for(i=1;i<(header.insnum+1);i++)
  {
	printf("Downloading voice %d....", i);
	fflush(stdout);
        DosSetFilePtr(modin, (int)paraptr[i-1]<<4, FILE_BEGIN, &Wrote);

	// and load sample info
	rc = DosRead(modin, &s, sizeof(SCREAMSAMPLE), &Wrote);
        ON_ERROR(rc, S3MTestAndLoad_Err);

	strncpy(SampInfo->Name, s.sampname,28);
	SampInfo->Name[28] = 0;
	SampInfo->Finetune = s.c2spd & 0xFFFF;  //lower 16 bits only
	SampInfo->Length = s.length;
	SampInfo->Repeat = s.loopbeg;
	SampInfo->End    = s.loopend - 1;
	SampInfo->Volume = s.volume;
	SampInfo->Mode  = 0;
	hdr = 0;
	if(s.flags & 1)            SampInfo->Mode |= VC_LOOP_ENABLE;
	if(s.flags & 4) {
	       	hdr |= DMA_16;
		SampInfo->Mode |= VC_DATA_TYPE;
	}
	if(header.fileformat != 1) 	hdr |= DMA_CVT_2;

	if(memcmp(s.scrs,"SCRS",4) !=0)
 	{
		SampInfo->Length = 0;
		SampInfo->Volume = 0;
	}
	else
	{
		foffset = ( ( ( (int)s.memsegh) <<16 ) | s.memsegl ) << 4;
	        DosSetFilePtr(modin, foffset, FILE_BEGIN, &Wrote);
	        rc = DosRead(modin, SampMem, SampInfo->Length, &Wrote);
      	        ON_ERROR(rc, S3MTestAndLoad_Err);

		rc = UltiMODMemAlloc(SampInfo->Length + 16, &SampInfo->Offset);
      	        ON_ERROR(rc, S3MTestAndLoad_Err);

		rc = UltraDownload(SampMem, hdr, SampInfo->Offset,
                                   SampInfo->Length, TRUE);
  
		if(SampInfo->Mode & VC_LOOP_ENABLE) {
			temprep = SampInfo->Repeat;
		        SampInfo->Repeat += SampInfo->Offset;
			SampInfo->End    += SampInfo->Offset;
			//anti-click for end of sample
			for(j=0;j<16;j++)
				if(hdr & DMA_CVT_2) {
					lo = SampInfo->Repeat + j;
					UltraPeekData(&lo);
					UltraPokeData(SampInfo->End + j, lo);
				}
				else	UltraPokeData(SampInfo->End + j, *(SampMem + j + temprep));
		}
		else { 
			SampInfo->End = SampInfo->Offset + SampInfo->Length;
			SampInfo->Repeat = SampInfo->Offset;
			//anti-click for end of sample
			for(j=0;j<16;j++) UltraPokeData(SampInfo->End + j, 0);
		}  
	        UltraStartVoice(0,SampInfo->Offset,SampInfo->Repeat,SampInfo->End, SampInfo->Mode);
		UltraSetFrequency(0, 22050);
		UltraVectorLinearVolume(0, 200, (unsigned char)0x2F,(unsigned char)0);  
	        DosSleep(1000);
		hdr = 0;
		UltraVoiceStopped(&hdr);
		if(hdr) printf("Sample finished playing.\n");
		else    printf("Sample is still playing.\n");
		if((SampInfo->Mode & VC_LOOP_ENABLE) && !hdr) {
			UltraSetLoopMode(0, 0x00);	//stop loop
			printf("Stopped loop.\n");
		}
	        DosSleep(2000);
	        UltraStopVoice(0);
	}	
	SampInfo++;
  }

S3MTestAndLoad_Err:
  UltiMODMemFree();
  DosFreeMem(Samples);
  DosFreeMem(SampMem);
  DosFreeMem(paraptr);
  StopPlaying();
  return(TRUE);

}


int InitDevice()
{
   APIRET status;
   ULONG action;
   int k;

   status = DosOpen( "ULTRA1$", &GUSHandle, &action, 0,
			  FILE_NORMAL, FILE_OPEN,
   OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE | OPEN_FLAGS_WRITE_THROUGH,
			  NULL );
   if(status)                   return(FALSE);

   if(UltraGetAccess() != 0) {
	DosClose(GUSHandle);
	return(FALSE); //not only owner
   }  
   if(UltraGetDriverVersion(&k)) {
	DosClose(GUSHandle);
	return(FALSE); //driver too old!
   }
   if(k < 85) {
	DosClose(GUSHandle);
	return(FALSE); //driver too old!
   }

 return(TRUE);
}

int StopPlaying()
{
  APIRET rc;
  
  UltraDisableOutput();

  rc = UltraReleaseAccess();	//gives other programs access to the GUS
  
  rc = DosClose(GUSHandle);

  return(TRUE);
}

[ RETURN TO DIRECTORY ]