コード例 #1
0
ファイル: sound.c プロジェクト: bernds/UAE
inline void direct_check_sound_buffers(void) {
    int played_size = direct_sndbufpt - direct_buffers[CurrentBuffer];

    sound_bytes++;
    if ((!IsPlaying) && played_size >= currprefs.sound_minbsiz) {
	SND_DirectWrite(played_size, sound_curfreq);
	if (currprefs.sound_adjust) {
	    unsigned int cur_clock, new_freq;

	    if (last_clock == 0)
		last_clock = uclock();
	    else {
		cur_clock = uclock();
		new_freq = (unsigned long long) sound_bytes * UCLOCKS_PER_SEC / (cur_clock-last_clock);
		interpol_freq(new_freq);
		last_clock = cur_clock;
	    }
	    sound_bytes = 0;
	}
	CurrentBuffer = !CurrentBuffer;
	direct_sndbufpt = direct_buffers[CurrentBuffer];
    } else if (played_size >= currprefs.sound_maxbsiz) {
	if (currprefs.sound_adjust)
	    interpol_freq(currprefs.sound_freq);
	while(IsPlaying);
	SND_DirectWrite(currprefs.sound_maxbsiz, sound_curfreq);
	CurrentBuffer = !CurrentBuffer;
	direct_sndbufpt = direct_buffers[CurrentBuffer];
	last_clock=0;
    }
}
コード例 #2
0
ファイル: timers.c プロジェクト: fourks/bb.js
/*following functions are architecture dependent */
void tl_update_time(void)
{
#ifdef POOL_SOUND
    update_sound();
#endif
#ifdef HAVE_UCLOCK
    currenttime=uclock();
#else
#ifdef USE_CLOCK 
    currenttime=clock();
#else
#ifdef HAVE_GETTIMEOFDAY
    do {
	gettimeofday(&currenttime, &tzp);
    } while (currenttime.tv_usec > 999999);
#else
#ifdef HAVE_FTIME
    ftime(&currenttime);
#endif
#endif
#endif
#endif
#ifdef _plan9_
    currenttime = plan9_msec();
#endif
}
コード例 #3
0
ファイル: systimer.c プロジェクト: GENiEBEN/fanohuff
void InitTimer( void )
{
#if defined(WINDOWS_TIMER)

  __int64 freq;

  global_timer.period = 0.0;
  if( QueryPerformanceFrequency( (LARGE_INTEGER *)&freq ) )
  {
    global_timer.period = 1.0 / (double) freq;
    QueryPerformanceCounter( (LARGE_INTEGER *)&global_timer.t0 );
  }
  else
    global_timer.t0 = (__int64) GetTickCount();

#elif defined(DOS_TIMER)

  global_timer.t0 = uclock();

#elif defined(GTOD_TIMER)

  gettimeofday( &global_timer.t0, NULL );

#endif
}
コード例 #4
0
ファイル: status.c プロジェクト: cdrr/MAME_hack
void StatusUpdateFPS(BOOL bShow, int nSpeed, int nFPS, int nMachineFPS, int nFrameskip, int nVecUPS)
{
    char buf[100];
    uclock_t now;
    
    if (hStatus == NULL)
        return;
    
    if (MAME32App.m_bMamePaused || MAME32App.m_bAutoPaused)
    {
        StatusUpdate();
        return;
    }

    if (bShow == FALSE)
    {
        SendMessage(hStatus, SB_SETTEXT, 1, (LPARAM)"");
        return;
    }

    now = uclock();
    
    /* update twice a second or so */
    if ((now - prev_update_time) < (UCLOCKS_PER_SEC/2))
        return;
    
    sprintf(buf, "\t\tfskp%2d%4d%%%4d/%d fps", nFrameskip, nSpeed, nFPS, nMachineFPS);
    
    SendMessage(hStatus, SB_SETTEXT, 1, (LPARAM)buf);
    
    prev_update_time = now;
}
コード例 #5
0
ファイル: timer.c プロジェクト: dafyddcrosby/meka
void        OSD_Timer_Initialize (void)
{
    // Select timer to use
    if (OSD_X86CPU_Has_RDTSC ())
    {
        DWORD   a, b;
        s64     time_start, time_end;

        timer_func_get_cycles_current = OSD_Timer_GetCyclesCurrent_RDTSC;

        a = uclock();
        // Wait some time to let everything stabilize
        do
        {
            b = uclock();
            // get the starting cycle count
            time_start = OSD_Timer_GetCyclesCurrent_RDTSC();
        } while (b - a < UCLOCKS_PER_SEC/2);

        // Now wait for 1/2 second
        do
        {
            a = uclock();
            // get the ending cycle count
            time_end = OSD_Timer_GetCyclesCurrent_RDTSC();
        } while (a - b < UCLOCKS_PER_SEC/2);

        // Compute timer_cycles_per_second
        timer_cycles_per_second = (time_end - time_start) * 2;
    }
    else
    {
        Quit_Msg ("Error initializating timer!");
    }
    /*
    else
    {
        timer_func_get_cycles_current = OSD_Timer_GetCyclesCurrent_DOS_uclock;
        timer_cycles_per_second = UCLOCKS_PER_SEC;
    }
    */
}
コード例 #6
0
ファイル: MAIN.CPP プロジェクト: v-zor/games.for.dosbox
int main(int argc, char *argv[])
{
    BITMAP *buffer;

    allegro_init();
    install_keyboard();
    install_timer();
    int buttons = install_mouse();

    set_color_depth(32);
    if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) {
        set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
        allegro_message("Unable to set gfx mode\n%s\n", allegro_error);
        return 1;
    }


    uclock_t start;
    buffer = create_bitmap(SCREEN_W, SCREEN_H);


    zelda::image::Image *img = new zelda::image::Image;
    img->load_pcx("./pics/test3.pcx");

    while (!key[KEY_ESC]) {

        blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
        blit(img->get_bmp(), screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);

        start = uclock();
        while (uclock() < start + UCLOCKS_PER_SEC / 1500)
            ;
        //usleep(50000);

    }

    destroy_bitmap(buffer);
    return 0;
}
コード例 #7
0
ファイル: timers.c プロジェクト: Jheengut/gmerlin
/*following functions are architecture dependent */
void
tl_update_time (void)
{
#ifdef __BEOS__
  currenttime = system_time ();
#else
#ifdef _WIN32
  QueryPerformanceCounter (&currenttime);
#else
#ifdef USE_ALLEGRO
  if (allegromode)
    {
      if (counter == -1)
	{
	  LOCK_VARIABLE (counter);
	  LOCK_FUNCTION (timer);
	  install_int (timer, 1000 / TICKSPERSEC);
	  ainstalled = 1;
	  counter = 0;
	}
      currenttime = counter;
      return;
    }
#endif
#ifdef HAVE_UCLOCK
  currenttime = uclock ();
#else
#ifdef USE_CLOCK
  currenttime = clock ();
#else
#ifdef HAVE_GETTIMEOFDAY

  do
    {
      gettimeofday (&currenttime, &tzp);
    }
  while (currenttime.tv_usec > 999999);
#else
#ifdef HAVE_FTIME
  ftime (&currenttime);
#endif
#endif
#endif
#endif
#endif
#endif
#ifdef _plan9_
  currenttime = plan9_msec ();
#endif
}
コード例 #8
0
ファイル: utils.c プロジェクト: trevornunes/HuGo
static double osd_getTime(void)
{
#ifdef WIN32
  return (SDL_GetTicks() * 1e-3);
#elif defined(DJGPP)
  return uclock() * (1.0 / UCLOCKS_PER_SEC);
#else
  struct timeval tp;

  gettimeofday(&tp, NULL);
  // printf("current microsec = %f\n",tp.tv_sec + 1e-6 * tp.tv_usec);
  return tp.tv_sec + 1e-6 * tp.tv_usec;
#endif
}
コード例 #9
0
ファイル: systimer.c プロジェクト: GENiEBEN/fanohuff
double GetTime( void )
{
#if defined(WINDOWS_TIMER)

  __int64 t;

  if( global_timer.period > 0.0 )
  {
    QueryPerformanceCounter( (LARGE_INTEGER *)&t );
    return global_timer.period * (double) (t - global_timer.t0);
  }
  else
    return 0.001 * (double) (GetTickCount() - (int) global_timer.t0);

#elif defined(DOS_TIMER)

  return (1.0 / UCLOCKS_PER_SEC) * (double) (uclock() - global_timer.t0);

#elif defined(GTOD_TIMER)

  struct timeval tv;

  gettimeofday( &tv, NULL );

  tv.tv_sec -= global_timer.t0.tv_sec;
  tv.tv_usec -= global_timer.t0.tv_usec;
  if( tv.tv_usec < 0 )
  {
    --tv.tv_sec;
    tv.tv_usec += 1000000;
  }

  return (double) tv.tv_sec + 0.000001 * (double) tv.tv_usec;

#else

  return 0.0;

#endif
}
コード例 #10
0
ファイル: writtest.c プロジェクト: svn2github/freedos-32
int main()
{
    unsigned k = 0;
    BYTE     buffer[512];
    unsigned long long start_time;

    fd32_event_init();
    if (fdc_setup(drive_detected) < 0) return -1;
    atexit(dispose);

    printf("Going to write some data in all sectors...\n");
    getchar();
    start_time = uclock();
    do
    {
        memset(buffer, k, sizeof(buffer));
        int res = floppy_write(&drive0, k, 1, buffer);
        if (res == FDC_NODISK) break;
        else if (res < 0) printf("Error on block %u\n", k);
        if (k % (drive0.fdd->fmt->sec_per_trk * drive0.fdd->fmt->heads) == 0)
            printf("%llu: block %u written\n", uclock() * 1000 / UCLOCKS_PER_SEC, k);
    }
    while (++k < drive0.fdd->fmt->size);
    printf("Write test elapsed in %llu ms\n", (uclock() - start_time) * 1000 / UCLOCKS_PER_SEC);
    puts("Going to read data from all sectors...\n");
    getchar();
    k = 0;
    start_time = uclock();
    do
    {
        BYTE check[512];
        memset(check, k, sizeof(check));
        int res = floppy_read(&drive0, k, 1, buffer);
        if (res == FDC_NODISK) break;
        else if (res < 0) printf("Error on block %u\n", k);
        if (k % (drive0.fdd->fmt->sec_per_trk * drive0.fdd->fmt->heads) == 0)
            printf("%llu: block %u read\n", uclock() * 1000 / UCLOCKS_PER_SEC, k);
        if (memcmp(buffer, check, sizeof(buffer)))
            printf("Block %u MISMATCH!\n", k);
    }
    while (++k < drive0.fdd->fmt->size);
    printf("Read test elapsed in %llu ms\n", (uclock() - start_time) * 1000 / UCLOCKS_PER_SEC);
    printf("All tests completed.\n");
    return 0;
}
コード例 #11
0
ファイル: dosmisc.c プロジェクト: nidheeshdas/Algosim
long GrMsecTime( void )
{
  return (uclock()/(UCLOCKS_PER_SEC/1000));
}
コード例 #12
0
ファイル: sys_dos.c プロジェクト: Blzut3/Engoo
/*
================
Sys_FloatTime
================
*/
double Sys_FloatTime (void)
{
// 2000-07-28 DOSQuake time running too fast fix by Norberto Alfredo Bensa  start
	// Warning!!! uclock() is not an ANSI-C standard function
	return (double) uclock() / (double) UCLOCKS_PER_SEC;
/*
	int			r;
	unsigned	t, tick;
	double		ft, time;
	static int	sametimecount;

	Sys_PushFPCW_SetHigh ();

//	{static float t = 0; t=t+0.05; return t;}	// DEBUG

	t = *(unsigned short*)real2ptr(0x46c) * 65536;

	dos_outportb(0x43, 0); // latch time
	r = dos_inportb(0x40);
	r |= dos_inportb(0x40) << 8;
	r = (r-1) & 0xffff;

	tick = *(unsigned short*)real2ptr(0x46c) * 65536;
	if ((tick != t) && (r & 0x8000))
		t = tick;

	ft = (double) (t+(65536-r)) / 1193200.0;
	time = ft - oldtime;
	oldtime = ft;

	if (time < 0)
	{
		if (time > -3000.0)
			time = 0.0;
		else
			time += 3600.0;
	}

	curtime += time;

	if (curtime == lastcurtime)
	{
		sametimecount++;

		if (sametimecount > 100000)
		{
			curtime += 1.0;
			sametimecount = 0;
		}
	}
	else
	{
		sametimecount = 0;
	}

	lastcurtime = curtime;

	Sys_PopFPCW ();

	return curtime;
*/
// 2000-07-28 DOSQuake time running too fast fix by Norberto Alfredo Bensa  end
}
コード例 #13
0
ファイル: circles.cpp プロジェクト: honnorat/meshit
int main(int argc, char** argv)
{
    meshit::SetLogLevel(MESHIT_INFO_LOG_LEVEL);

    // creates geometry structure
    meshit::SplineGeometry geom;
    int bc_num = 1;

    // outer boundary
    uint32_t face1 = geom.AddFace("face1");
    geom.AddCircle({0.0, 1.5}, 3.0, 1e99, ++bc_num, face1);

    // add hole
    geom.AddCircle({0.0, 0.0}, 1.0, 0.1, ++bc_num, 0, face1);

    // Add inclusion
    uint32_t face2 = geom.AddFace("face2");
    std::vector<meshit::Point2d> ellipse = {{0.0,  2.25},
                                            {-1.5, 2.25},
                                            {-1.5, 1.75},
                                            {-1.5, 1.25},
                                            {+0.0, 1.25},
                                            {+1.5, 1.25},
                                            {+1.5, 1.75},
                                            {+1.5, 2.25}};
    geom.AddSpline(ellipse, 0.05, ++bc_num, face2, face1);

    meshit::Mesh mesh;
    meshit::MeshingParameters mp;
    mp.optsteps2d = 5;
    mp.maxh = 0.2;

    double cc;
    cc = uclock();
    mesh.BuildFromSplineGeometry(geom, mp);
    MESHIT_LOG_INFO("~ meshing  : " << uclock() - cc << " s.");

    cc = uclock();
    mesh.PrintQuality();
    MESHIT_LOG_INFO("~ quality  : " << uclock() - cc << " s.");

    cc = uclock();
    mesh.CheckOverlappingBoundary();
    MESHIT_LOG_INFO("~ checkover: " << uclock() - cc << " s.");

    mesh.PrintMemInfo(std::cout);
    MESHIT_LOG_INFO("AverageH(0) = " << mesh.AverageH(0));
    MESHIT_LOG_INFO("AverageH(1) = " << mesh.AverageH(face1));
    MESHIT_LOG_INFO("AverageH(2) = " << mesh.AverageH(face2));

    cc = uclock();
    mesh.Export("circles.msh");
    MESHIT_LOG_INFO("~ export   : " << uclock() - cc << " s.");

    cc = uclock();
    mesh.Save("circles.meshit");
    MESHIT_LOG_INFO("~ save     : " << uclock() - cc << " s.");

    mesh.Refine();
    mesh.PrintQuality();
    mesh.CheckSurface();
    mesh.CheckOverlappingBoundary();
    mesh.PrintMemInfo(std::cout);
    MESHIT_LOG_INFO("AverageH(0) = " << mesh.AverageH(0));
    MESHIT_LOG_INFO("AverageH(1) = " << mesh.AverageH(face1));
    MESHIT_LOG_INFO("AverageH(2) = " << mesh.AverageH(face2));
    mesh.Export("circles_fine.msh");

    return 0;
}
コード例 #14
0
ファイル: MAME.C プロジェクト: neiderm/arcade
/***************************************************************************

  This function takes care of refreshing the screen, processing user input,
  and throttling the emulation speed to obtain the required frames per second.

***************************************************************************/
int updatescreen(void)
{
	static int framecount = 0;


	/* read hi scores from disk */
	if (hiscoreloaded == 0 && *gamedrv->hiscore_load)
		hiscoreloaded = (*gamedrv->hiscore_load)(hiscorename);

	/* if the user pressed ESC, stop the emulation */
	if (osd_key_pressed(OSD_KEY_ESC)) return 1;

	/* if the user pressed F3, reset the emulation */
	if (osd_key_pressed(OSD_KEY_F3))
	{
		/* write hi scores to disk */
		if (hiscoreloaded != 0 && *gamedrv->hiscore_save)
			(*gamedrv->hiscore_save)(hiscorename);
		hiscoreloaded = 0;

		return 2;
	}

        if (osd_key_pressed(OSD_KEY_F9)) {
                if (++VolumePTR > 4) VolumePTR = 0;
                ActualVolume = VolumiDefault[VolumePTR];
                osd_set_mastervolume(ActualVolume);
		while (osd_key_pressed(OSD_KEY_F9)) {
                  if (*drv->sh_update) {
		     (*drv->sh_update)();	/* update sound */
		     osd_update_audio();
                  }
                }
        }

	if (osd_key_pressed(OSD_KEY_P)) /* pause the game */
	{
		struct DisplayText dt[2];
		int key;


		dt[0].text = "PAUSED";
		dt[0].color = gamedrv->paused_color;
		dt[0].x = gamedrv->paused_x;
		dt[0].y = gamedrv->paused_y;
		dt[1].text = 0;
		displaytext(dt,0);

                osd_set_mastervolume(0);
		while (osd_key_pressed(OSD_KEY_P)) {
                  if (*drv->sh_update) {
		     (*drv->sh_update)();	/* update sound */
		     osd_update_audio();
                  }
                }
                	/* wait for key release */
		do
		{
			key = osd_read_key();

			if (key == OSD_KEY_ESC) return 1;
			else if (key == OSD_KEY_TAB)
			{
				if (setdipswitches()) return 1;
				(*drv->vh_update)(Machine->scrbitmap);	/* redraw screen */
				displaytext(dt,0);
			}
		} while (key != OSD_KEY_P);
		while (osd_key_pressed(key));
                osd_set_mastervolume(ActualVolume);
	}

	/* if the user pressed TAB, go to dipswitch setup menu */
	if (osd_key_pressed(OSD_KEY_TAB))
	{
                osd_set_mastervolume(0);
		while (osd_key_pressed(OSD_KEY_TAB)) {
                  if (*drv->sh_update) {
		     (*drv->sh_update)();	/* update sound */
		     osd_update_audio();
                  }
                }
		if (setdipswitches()) return 1;
                osd_set_mastervolume(ActualVolume);
	}

	/* if the user pressed F8, go to keys setup menu */
	if (osd_key_pressed(OSD_KEY_F8))
	{
                osd_set_mastervolume(0);
		while (osd_key_pressed(OSD_KEY_F8)) {
                  if (*drv->sh_update) {
		     (*drv->sh_update)();	/* update sound */
		     osd_update_audio();
                  }
                }
                if (setkeysettings()) return 1;
                osd_set_mastervolume(ActualVolume);
	}

	/* if the user pressed F4, show the character set */
	if (osd_key_pressed(OSD_KEY_F4))
	{
                osd_set_mastervolume(0);
		while (osd_key_pressed(OSD_KEY_F4)) {
                  if (*drv->sh_update) {
		     (*drv->sh_update)();	/* update sound */
		     osd_update_audio();
                  }
                }
		if (showcharset()) return 1;
                osd_set_mastervolume(ActualVolume);
	}

	if (*drv->sh_update)
	{
		(*drv->sh_update)();	/* update sound */
		osd_update_audio();
	}

	if (++framecount > frameskip)
	{
		static int showfps,f11pressed;
		static int throttle = 1,f10pressed;
		uclock_t curr,mtpf;
		#define MEMORY 10
		static uclock_t prev[MEMORY];
		static int i,fps;


		framecount = 0;

		if (osd_key_pressed(OSD_KEY_F11))
		{
			if (f11pressed == 0)
			{
				showfps ^= 1;
				if (showfps == 0) clearbitmap(Machine->scrbitmap);
			}
			f11pressed = 1;
		}
		else f11pressed = 0;

		if (osd_key_pressed(OSD_KEY_F10))
		{
			if (f10pressed == 0) throttle ^= 1;
			f10pressed = 1;
		}
		else f10pressed = 0;


		(*drv->vh_update)(Machine->scrbitmap);	/* update screen */

		if (showfps)
		{
			drawgfx(Machine->scrbitmap,Machine->gfx[0],gamedrv->charset[(fps%1000)/100],gamedrv->white_text,0,0,0,0,0,TRANSPARENCY_NONE,0);
			drawgfx(Machine->scrbitmap,Machine->gfx[0],gamedrv->charset[(fps%100)/10],gamedrv->white_text,0,0,Machine->gfx[0]->width,0,0,TRANSPARENCY_NONE,0);
			drawgfx(Machine->scrbitmap,Machine->gfx[0],gamedrv->charset[fps%10],gamedrv->white_text,0,0,2*Machine->gfx[0]->width,0,0,TRANSPARENCY_NONE,0);
		}

		osd_update_display();

		osd_poll_joystick();

		/* now wait until it's time to trigger the interrupt */
		do
		{
			curr = uclock();
		} while (video_sync == 0 && throttle != 0 && (curr - prev[i]) < (frameskip+1) * UCLOCKS_PER_SEC/drv->frames_per_second);

		i = (i+1) % MEMORY;

		mtpf = ((curr - prev[i])/(MEMORY))/2;
		if (mtpf) fps = (UCLOCKS_PER_SEC+mtpf)/2/mtpf;

		prev[i] = curr;
	}

	return 0;
}
コード例 #15
0
ファイル: SEALINTF.C プロジェクト: kidaa/Provenance
int msdos_init_sound(int *rate, int card)
{
  int i;

  seal_sample_rate = *rate;
  seal_sound_card  = card;

  if (AInitialize() != AUDIO_ERROR_NONE)
    return 1;

  /* Ask the user if no sound card was chosen */
  if (seal_sound_card == -1)
  {
    unsigned int k;

    printf("\n SELECT YOUR AUDIO DEVICE :\n\n"
            " AWE32/64 playback requires onboard DRAM,\n"
            " Sound Blaster playback is the most compatible & better for emulation\n\n");

    for (k = 0;k < AGetAudioNumDevs();k++)
    {
      if (AGetAudioDevCaps(k,&caps) == AUDIO_ERROR_NONE)
        printf("  %2d. %s\n",k,caps.szProductName);
    }
    printf("\n");

    if (k < 10)
    {
      i = getch();
      seal_sound_card = i - '0';
    }
    else
      scanf("%d",&seal_sound_card);
  }

  /* initialize SEAL audio library */
  if (seal_sound_card == 0)     /* silence */
  {
    /* update the Machine structure to show that sound is disabled */
    seal_sample_rate = 0;
    exit(0);
    return 0;
  }

  /* open audio device */
  /* info.nDeviceId = AUDIO_DEVICE_MAPPER;*/
  info.nDeviceId = seal_sound_card;
  /* always use 16 bit mixing if possible - better quality and same speed of 8 bit */
  info.wFormat = AUDIO_FORMAT_16BITS | AUDIO_FORMAT_STEREO | AUDIO_FORMAT_RAW_SAMPLE;

  info.nSampleRate = seal_sample_rate;
  if (AOpenAudio(&info) != AUDIO_ERROR_NONE)
  {
    return (1);
  }

  AGetAudioDevCaps(info.nDeviceId,&caps);
  printf("Using `%s' at %d-bit %s %u Hz\n",
  caps.szProductName,
  info.wFormat & AUDIO_FORMAT_16BITS ? 16 : 8,
  info.wFormat & AUDIO_FORMAT_STEREO ? "stereo" : "mono",
  info.nSampleRate);

  /* open and allocate voices, allocate waveforms */
  if (AOpenVoices(NUMVOICES) != AUDIO_ERROR_NONE)
  {
    printf("voices initialization failed\n");
    return 1;
  }

  for (i = 0; i < NUMVOICES; i++)
  {
    if (ACreateAudioVoice(&hVoice[i]) != AUDIO_ERROR_NONE)
    {
      printf("voice #%d creation failed\n",i);
      return 1;
    }

    ASetVoicePanning(hVoice[i],128);

    lpWave[i] = 0;
  }

  /* update the Machine structure to reflect the actual sample rate */
  *rate = seal_sample_rate = info.nSampleRate;

  {
    uclock_t a,b;
    LONG start,end;


    if ((lpWave[0] = (LPAUDIOWAVE)malloc(sizeof(AUDIOWAVE))) == 0)
      return 1;

    lpWave[0]->wFormat = AUDIO_FORMAT_8BITS | AUDIO_FORMAT_MONO;
    lpWave[0]->nSampleRate = seal_sample_rate;
    lpWave[0]->dwLength = 3*seal_sample_rate;
    lpWave[0]->dwLoopStart = 0;
    lpWave[0]->dwLoopEnd = 3*seal_sample_rate;
    if (ACreateAudioData(lpWave[0]) != AUDIO_ERROR_NONE)
    {
      free(lpWave[0]);
      lpWave[0] = 0;

      return 1;
    }

    memset(lpWave[0]->lpData,0,3*seal_sample_rate);
    /* upload the data to the audio DRAM local memory */
    AWriteAudioData(lpWave[0],0,3*seal_sample_rate);
    APrimeVoice(hVoice[0],lpWave[0]);
    ASetVoiceFrequency(hVoice[0],seal_sample_rate);
    ASetVoiceVolume(hVoice[0],0);
    AStartVoice(hVoice[0]);

    a = uclock();
    /* wait some time to let everything stabilize */
    do
    {
      osd_update_audio();
      b = uclock();
    } while (b-a < UCLOCKS_PER_SEC/10);

    a = uclock();
    AGetVoicePosition(hVoice[0],&start);
    do
    {
      osd_update_audio();
      b = uclock();
    } while (b-a < UCLOCKS_PER_SEC);
    AGetVoicePosition(hVoice[0],&end);

    nominal_sample_rate = seal_sample_rate;
    seal_sample_rate = end - start;

    AStopVoice(hVoice[0]);
    ADestroyAudioData(lpWave[0]);
    free(lpWave[0]);
    lpWave[0] = 0;
  }

  osd_set_mastervolume(0);    /* start at maximum volume */

  return 0;
}
コード例 #16
0
int dd_timer_settime( timer_t timerid,	/* timer ID */
		   int flags,	/* absolute or relative */
		   const struct itimerspec *value,	/* time to be set */
		   struct itimerspec *ovalue	/* previous time set (NULL=no 
						 * result) */
     )
{
    struct itimerval itimer;
    struct event *event = ( struct event * )timerid;
    struct event **ppevent;

    TIMESPEC_TO_TIMEVAL( &event->it_interval, &value->it_interval );
    TIMESPEC_TO_TIMEVAL( &event->it_value, &value->it_value );

    /*
     * if .it_value is zero, the timer is disarmed 
     */
    if( !timerisset( &event->it_value ) )
    {
	dd_timer_cancel( timerid );
	return 0;
    }

    dd_block_timer(  );

#ifdef TIMER_PROFILE
    event->expected_ms =
	( event->it_value.tv_sec * MS_PER_SEC ) +
	( event->it_value.tv_usec / US_PER_MS );
    event->start = uclock(  );
#endif
    if( event->next )
    {
	TIMERDBG
	    ( "calling timer_settime with a timer that is already on the queue." );
    }

    /*
     * We always want to make sure that the event at the head of the queue
     * has a timeout greater than the itimer granularity. Otherwise we end up 
     * with the situation that the time remaining on an itimer is greater
     * than the time at the head of the queue in the first place. 
     */
    timerroundup( &event->it_value, g_granularity );

    timerclear( &itimer.it_value );
    getitimer( ITIMER_REAL, &itimer );
    if( timerisset( &itimer.it_value ) )
    {
	// reset the top timer to have an interval equal to the remaining
	// interval 
	// when the timer was cancelled.
	if( event_queue )
	{
	    if( timercmp
		( &( itimer.it_value ), &( event_queue->it_value ), > ) )
	    {
		// it is an error if the amount of time remaining is more
		// than the amount of time 
		// requested by the top event.
		// 
		TIMERDBG( "timer_settime: TIMER ERROR!" );

	    }
	    else
	    {
		// some portion of the top event has already expired.
		// Reset the interval of the top event to remaining
		// time left in that interval.
		// 
		event_queue->it_value = itimer.it_value;

		// if we were the earliest timer before now, we are still the 
		// earliest timer now.
		// we do not need to reorder the list.
	    }
	}
    }
コード例 #17
0
ファイル: fedup.c プロジェクト: 10crimes/code
void main(void) {
  
  int xy,i,c,x,y,front,back,n,minc,maxc;
  float dzdx,dzdy,a,b,dot,norm,tmp;
  long p,q;
  RGB rgb;
  long starttime;
  int numframes;
  
  // srand(456789);
  srand((int)time(NULL));
  // printf("%d\n",(int)time(NULL));
  
  
  mytime=10;
  maxc=0; minc=255;
  
  
  // Set up ripples
  numripples=3;
  for (i=0; i<numripples; i++) {
    newripple(i);
  }

  Map2d<int> dzdxmap=Map2d<int>(scrwid,scrhei);
  Map2d<int> dzdymap=Map2d<int>(scrwid,scrhei);  
  
  allegro_init ();
  install_keyboard ();
  install_timer ();
  set_gfx_mode (GFX_AUTODETECT, scrwid, scrhei, 0, 0);
  set_pallete (desktop_palette);
  buffer = create_bitmap (scrwid, scrhei);
  clear (buffer);
  
  // Set up grayscale colours
  for (c=0;c<=255;c++) {
    i=0;
    rgb.r=c*63/255;
    rgb.g=0;
    rgb.b=0;
    set_color(c,&rgb);
    // colors[c]=GrAllocColor(c,i,i);
  }
  
  PALLETE my_pallete;
  BITMAP *scr_buffer;
  scr_buffer = load_bitmap("paulcld.pcx",my_pallete);
  set_pallete (my_pallete);
  blit (scr_buffer, screen, 0,0,0,0,320,200);

  
  // circlefill (buffer, x, y, 3, 255);
  textout_centre (buffer, font, "Press SPACE!", 60, 220, 4);
  
  blit (buffer, screen, 0, 0, 0, 0, scrwid, scrhei);
  
  starttime=uclock();
  numframes=0;
  while(!key[KEY_ESC]) {
    for (x=0; x<scrwid; x=x+jump) {
      for (y=0; y<scrhei; y=y+jump) {
        dzdx=0;
        dzdy=0;
        for (i=0;i<numripples;i++) {
          ripples[i].front=ripples[i].v*(mytime-ripples[i].st);
          ripples[i].back=ripples[i].v*(mytime-ripples[i].st)-ripples[i].w;
          if (ripples[i].back>scrwid)
            newripple(i);
        }
        for (i=0;i<numripples;i++) {
          xy=(sqrt((x-ripples[i].x)*(x-ripples[i].x)+(y-ripples[i].y)*(y-ripples[i].y)));
          // printf("xy%i",xy);
          // printf("x%i",x);
          // printf("y%i",y);
          // printf("rx%i",ripples[i].x);
          // printf("ry%i",ripples[i].y);
          // printf("f%i\n",front);
          // printf("b%i\n",back);
          if ((xy>2)&&(xy<ripples[i].front)&&(xy>ripples[i].back)) {
            // printf("*********");
            a=pi/ripples[i].w*sin(2*pi*ripples[i].n/ripples[i].w*(xy-ripples[i].v*(mytime-ripples[i].st)));
            // printf("a%f",a);
            b=(float)10.0/mysquare(xy+1);
            // printf("b%f",b);
            // norm=1500/(mysquare(xy))*(exp(3*(xy-(ripples[i].v)*((mytime-ripples[i].st)))/ripples[i].w));
            norm=2.0*(xy-ripples[i].back)/(ripples[i].front-ripples[i].back);
            // printf("n%f",norm);
            dzdx=dzdx+a*b*(x-ripples[i].x)*ripples[i].w*norm;
            dzdy=dzdy+a*b*(y-ripples[i].y)*ripples[i].w*norm;
          }
        }

        // dot=dzdx*lx+dzdy*ly;
        // dot=dot*(dzdx*0.8+dzdy*0.6);
        // dot=dzdx*0.8+dzdy*0.6;
//        dot=dzdx * 1 * 0.8 + dzdy * 1 * 0.6;
//        float f=mymod(0.5+dot*0.5*scale);

        dzdxmap.pos[x][y]=refract*dzdx;
        dzdymap.pos[x][y]=refract*dzdy;

        if (x>0 && y>0) {
          int nwdx=dzdxmap.pos[x-jump][y-jump];
          int nedx=dzdxmap.pos[x][y-jump];
          int swdx=dzdxmap.pos[x-jump][y];
          int sedx=dzdxmap.pos[x][y];
          int nwdy=dzdymap.pos[x-jump][y-jump];
          int nedy=dzdymap.pos[x][y-jump];
          int swdy=dzdymap.pos[x-jump][y];
          int sedy=dzdymap.pos[x][y];
          for (int i=0;i<jump;i++)
            for (int j=0;j<jump;j++) {
              float a=(float)i/(float)jump;
              float d=(float)j/(float)jump;
              int idzdx=(1.0-a)*(1.0-d)*nwdx+(a)*(1.0-d)*nedx+(1.0-a)*(d)*swdx+(a)*(d)*sedx;
              int idzdy=(1.0-a)*(1.0-d)*nwdy+(a)*(1.0-d)*nedy+(1.0-a)*(d)*swdy+(a)*(d)*sedy;
              int rx=x-jump+i+idzdx;
              int ry=y-jump+j+idzdy;
              if (rx>=0 && ry>=0 && rx<scrwid && ry<scrhei)
                c=getpixel(scr_buffer,rx,ry);
              else
                c=0;
//              c=ucharchop(8*sqrt(idzdx*idzdx+idzdy*idzdy));
              putpixel(buffer,x-jump+i,y-jump+j,c);
            }
        
        }
        // GrFilledBox(x,y,x+jump-1,y+jump-1,colors[c]);
      }
    }
    /* for (i=0;i<numripples;i++) {
         mycircle(ripples[i].x,ripples[i].y,ripples[i].front,colors[0]);
         mycircle(ripples[i].x,ripples[i].y,ripples[i].back,colors[0]);
       }*/
    blit (buffer, screen, 0, 0, 0, 0, scrwid, scrhei);
    mytime=mytime+2;
    numframes++;
//    save_bitmap(getnextfilename("bmp"),buffer,my_pallete);
  }
  destroy_bitmap(buffer);
  allegro_exit();
  printf("%d frames per second.\n",UCLOCKS_PER_SEC*numframes/(uclock()-starttime));
  printf("max col %d\n",maxc);
  printf("min col %d\n",minc);
  
}
コード例 #18
0
ファイル: ticker.c プロジェクト: CarnyPriest/SAMbuild
cycles_t osd_cycles(void)
{
	return uclock();
}
コード例 #19
0
ファイル: barath.c プロジェクト: CarnyPriest/SAMbuild
int barath_skip_next_frame(void)
{
  static uclock_t curr = 0;
  static uclock_t prev = 0;
  static uclock_t avg_uclocks = 0;
  static int frames_skipped = 0;
  static int sysload = 0;
  static float framerate = 1;
  static float speed = 1;
  static float lag_rate = -30;

  int skip_this_frame = barath_skip_this_frame();
  int scratch_time = uclock();
#ifdef barath_debug
  static float slow_speed = 1;
  int uclocks_per_frame = slow_speed * UCLOCKS_PER_SEC / video_fps;
#else
  int uclocks_per_frame = UCLOCKS_PER_SEC / video_fps;
#endif
  /* project target display time of this frame */
  uclock_t target = prev + (frames_skipped + 1) * uclocks_per_frame;

  /* if lagging by more than 2 frames don't try to make up for it */
  while (scratch_time - target > uclocks_per_frame * 2) {
    target += uclocks_per_frame;
    lag_rate++;
  }
  lag_rate *= 0.99;

  {
    static float framerateavg = 0;
    framerateavg = (framerateavg * 5 + 1 - skip_this_frame) / 6.0;
    framerate = (framerate * 5 + framerateavg) / 6.0;
  }
  if (throttle) {
    int leading = ((sysload > 33) && should_sleep_idle()) ? 0 : uclocks_per_frame;
    int sparetime = target - scratch_time;

    /* test for load-induced lags and set sysload */
    if (autoframeskip && should_sleep_idle()) {
      /* if lag is excessive and framerate is low then we have a system hiccup */
      if ((sysload < 100) && (lag_rate > 3) && (frameskip < max_autoframeskip)) {
	sysload++;
	lag_rate = 3;
      }
      /* after ~2000 frames of no lag start lowering sysload */
      else if (sysload && (fabs(lag_rate) < .00001)) {
	sysload--;
	lag_rate = .000011;	/* wait ~10 frames */
      }
    }
    if (autoframeskip) {
      /* this is an attempt at proportionate feedback to smooth things out */
      int feedback = ((sparetime - uclocks_per_frame / 2) / (uclocks_per_frame / 3));

      frameskip = ((1.0 - framerate) * (FRAMESKIP_LEVELS - 1)) - feedback;

#ifdef barath_debug
      debug_value = feedback;
#endif
      if (frameskip > max_autoframeskip)
	frameskip = max_autoframeskip;
      else if (frameskip < 0)
	frameskip = 0;
    }
    if (sparetime > 0) {
      /* if we're more than 2 frames ahead we need to resynch */
      if (sparetime > uclocks_per_frame * 2)
	target = scratch_time;
      else {
	/* idle until we hit frame ETA or leading */
	profiler_mark(PROFILER_IDLE);
	while (target - uclock() > leading)
	  if (should_sleep_idle())
	    usleep(100);
	profiler_mark(PROFILER_END);
      }
    }
    /* if we are behind we should force a skip: */
    else if (autoframeskip && (frameskip < max_autoframeskip)
	     && (frames_skipped < 1))
      modframe = FRAMESKIP_LEVELS * 2 - frameskip;

  }				/* if (throttle) */
  if (skip_this_frame && (frames_skipped < FRAMESKIP_LEVELS))
    frames_skipped++;
  else {
    /* update frame timer */
    prev = target;

    /* calculate average running speed for display purposes */
    scratch_time = curr;
    curr = uclock();
    avg_uclocks = (avg_uclocks * 5 + curr - scratch_time) / (6 + frames_skipped);
    speed = (speed * 5 + (float) uclocks_per_frame / avg_uclocks) / 6.0;
    /* double-forward average  */

    frames_skipped = 0;
  }

  /* give a little grace in case something else sets it off */
  if (should_sleep_idle() && autoframeskip && (sysload > 33)) {
    profiler_mark(PROFILER_IDLE);
    usleep(100);
    profiler_mark(PROFILER_END);
  }
  /* advance frameskip counter */
  if (modframe >= FRAMESKIP_LEVELS)
    modframe -= FRAMESKIP_LEVELS;
  modframe += frameskip;

  return barath_skip_this_frame();
}
コード例 #20
0
ファイル: dos.c プロジェクト: CarnyPriest/SAMbuild
int dos_skip_next_frame()
{
	static const int skiptable[FRAMESKIP_LEVELS][FRAMESKIP_LEVELS] =
	{
		{ 0,0,0,0,0,0,0,0,0,0,0,0 },
		{ 0,0,0,0,0,0,0,0,0,0,0,1 },
		{ 0,0,0,0,0,1,0,0,0,0,0,1 },
		{ 0,0,0,1,0,0,0,1,0,0,0,1 },
		{ 0,0,1,0,0,1,0,0,1,0,0,1 },
		{ 0,1,0,0,1,0,1,0,0,1,0,1 },
		{ 0,1,0,1,0,1,0,1,0,1,0,1 },
		{ 0,1,0,1,1,0,1,0,1,1,0,1 },
		{ 0,1,1,0,1,1,0,1,1,0,1,1 },
		{ 0,1,1,1,0,1,1,1,0,1,1,1 },
		{ 0,1,1,1,1,1,0,1,1,1,1,1 },
		{ 0,1,1,1,1,1,1,1,1,1,1,1 }
	};
	static const int waittable[FRAMESKIP_LEVELS][FRAMESKIP_LEVELS] =
	{
		{ 1,1,1,1,1,1,1,1,1,1,1,1 },
		{ 2,1,1,1,1,1,1,1,1,1,1,0 },
		{ 2,1,1,1,1,0,2,1,1,1,1,0 },
		{ 2,1,1,0,2,1,1,0,2,1,1,0 },
		{ 2,1,0,2,1,0,2,1,0,2,1,0 },
		{ 2,0,2,1,0,2,0,2,1,0,2,0 },
		{ 2,0,2,0,2,0,2,0,2,0,2,0 },
		{ 2,0,2,0,0,3,0,2,0,0,3,0 },
		{ 3,0,0,3,0,0,3,0,0,3,0,0 },
		{ 4,0,0,0,4,0,0,0,4,0,0,0 },
		{ 6,0,0,0,0,0,6,0,0,0,0,0 },
		{12,0,0,0,0,0,0,0,0,0,0,0 }
	};
	int i;
	uclock_t curr;
	static uclock_t prev_frames[FRAMESKIP_LEVELS]={0,0,0,0,0,0,0,0,0,0,0,0};
	static uclock_t prev=0;
	static int speed=100;

	/* now wait until it's time to update the screen */
	if (skiptable[frameskip][frameskip_counter] == 0)
	{
        	if (throttle)
        	{
        		uclock_t target,target2;
        		profiler_mark(PROFILER_IDLE);

        		/* wait until enough time has passed since last frame... */
        		target = prev +
        			waittable[frameskip][frameskip_counter] * UCLOCKS_PER_SEC/video_fps;

        		/* ... OR since FRAMESKIP_LEVELS frames ago. This way, if a frame takes */
        		/* longer than the allotted time, we can compensate in the following frames. */
        		target2 = prev_frames[frameskip_counter] +
        			FRAMESKIP_LEVELS * UCLOCKS_PER_SEC/video_fps;

        		if (target - target2 > 0) target = target2;
        		
        		curr = uclock();
        		
        		/* If we need to sleep more then half a second,
        		   we've somehow got totally out of sync. So
        		   if this happens we reset all counters */
        		if ((target - curr) > (UCLOCKS_PER_SEC / 2))
        		   for (i=0; i < FRAMESKIP_LEVELS; i++)
        		      prev_frames[i] = curr;
        		else
        		   while ((curr - target) < 0)
        		   {
        		      curr = uclock();
        		      if ((target - curr) > (UCLOCKS_PER_SEC / 1000) &&
        		          should_sleep_idle())
        		         usleep(100);
        		   }

        		profiler_mark(PROFILER_END);
        	}
        	else curr = uclock();

        	if (frameskip_counter == 0 && (curr - prev_frames[frameskip_counter]))
        	{
        		int divdr;

        		divdr = video_fps * (curr - prev_frames[frameskip_counter]) / (100 * FRAMESKIP_LEVELS);
        		speed = (UCLOCKS_PER_SEC + divdr/2) / divdr;
        	}

        	prev = curr;
        	for (i = 0;i < waittable[frameskip][frameskip_counter];i++)
        		prev_frames[(frameskip_counter + FRAMESKIP_LEVELS - i) % FRAMESKIP_LEVELS] = curr;

		if (throttle && autoframeskip && frameskip_counter == 0)
		{
			static int frameskipadjust;

			if (speed >= 100)
			{
				frameskipadjust++;
				if (frameskipadjust >= 3)
				{
					frameskipadjust = 0;
					if (frameskip > 0) frameskip--;
				}
			}
			else
			{
				if (speed < 80)
					frameskipadjust -= (90 - speed) / 5;
				else
				{
					/* don't push frameskip too far if we are close to 100% speed */
					if (frameskip < 8)
						frameskipadjust--;
				}

				while (frameskipadjust <= -2)
				{
					frameskipadjust += 2;
					if (frameskip < max_autoframeskip) frameskip++;
				}
			}
		}
	}
	
	frameskip_counter = (frameskip_counter + 1) % FRAMESKIP_LEVELS;
	
	return skiptable[frameskip][frameskip_counter];
}
コード例 #21
0
ファイル: timer.c プロジェクト: dafyddcrosby/meka
static s64  OSD_Timer_GetCyclesCurrent_DOS_uclock (void)
{
    return uclock();
}
コード例 #22
0
/*
================
Sys_DoubleTime
================
*/
double Sys_DoubleTime (void)
{
#if USE_UCLOCK_TIME
	return (double) uclock() / (double) UCLOCKS_PER_SEC;

#else
	int				r;
	unsigned		t, tick;
	double			ft, time;
	static int		sametimecount;

	Sys_PushFPCW_SetHigh ();

//{static float t = 0; t=t+0.05; return t;}	// DEBUG

	t = *(unsigned short*)real2ptr(0x46c) * 65536;

	dos_outportb(0x43, 0);	// latch time
	r = dos_inportb(0x40);
	r |= dos_inportb(0x40) << 8;
	r = (r - 1) & 0xffff;

	tick = *(unsigned short*)real2ptr(0x46c) * 65536;
	if ((tick != t) && (r & 0x8000))
		t = tick;

	ft = (double) (t + (65536 - r)) / 1193200.0;
	time = ft - oldtime;
	oldtime = ft;

	if (time < 0)
	{
		if (time > -3000.0)
			time = 0.0;
		else
			time += 3600.0;
	}

	curtime += time;

	if (curtime == lastcurtime)
	{
		sametimecount++;

		if (sametimecount > 100000)
		{
			curtime += 1.0;
			sametimecount = 0;
		}
	}
	else
	{
		sametimecount = 0;
	}

	lastcurtime = curtime;

	Sys_PopFPCW ();

	return curtime;
#endif	/* ! USE_UCLOCK_TIME */
}
コード例 #23
0
ファイル: galag.c プロジェクト: neiderm/arcade
/***************************************************************************

  This function takes care of refreshing the screen, processing user input,
  and throttling the emulation speed to obtain the required frames per second.

  IN: blocking (no longer used)
        1 == blocking, i.e. read keys, doesn't return until vblank complete.
        0 == non-blocking, i.e. read keys but return if not vblank

 ***************************************************************************/
int _updatescreen(int blocking)
{
    static uclock_t prev;

    static int this1, last1;
    static int this2, last2;
    static int this3, last3;
    static int thisct, lastct;

    float fps = sim_fps;

    thisct = code_pressed(KEYCODE_LCONTROL);

    if (thisct && lastct != thisct)
    {
        io_input[1] &= ~0x10; // see note for f_1F04
    }
    else
    {
        io_input[1] |= 0x10; // see note for f_1F04
    }
    lastct = thisct;

    if ( code_pressed(KEYCODE_RIGHT) )
    {
        io_input[1] &= ~2;
    }
    else
    {
        io_input[1] |= 2;
    }

    if ( code_pressed(KEYCODE_LEFT) )
    {
        io_input[1] &= ~8;
    }
    else
    {
        io_input[1] |= 8;
    }


    /* if the user pressed ESC, stop the emulation */
    if ( code_pressed(KEYCODE_ESC) ) return 1;

    // get keys for coin-in switch and start button, which need to be debounced

    this3 = code_pressed(KEYCODE_3);
    if (this3 && last3 != this3)
    {
        if (io_input[0] < 255)
        {
            io_input[0]++;
        }
    }
    last3 = this3;

    this1 = code_pressed(KEYCODE_1);
    if (this1 && last1 != this1)
    {
        if (io_input[0] > 0)
        {
            io_input[0]--;
        }
    }
    last1 = this1;

    this2 = code_pressed(KEYCODE_2);
    if (this2 && last2 != this2)
    {
        if (io_input[0] > 0)
        {
            io_input[0] -= 2;
        }
    }
    last2 = this2;


    if (1)
    {
        uclock_t curr;

        updatescreen();

        /* now wait until it's time to trigger the interrupt */
        do
        {
            curr = uclock();
        }
        while (curr - prev < UCLOCKS_PER_SEC / fps);

        vblank_work();
        prev = curr;
    }

    return 0;
}
コード例 #24
0
ファイル: fly.c プロジェクト: OrangeTide/plush
                       /* Main!!! */
void main() {
  char lastmessage[80] = "Fly 3.0"; // last message used for status line
  int draw_sky = 1;                 // do we draw the sky?
  int wait_vsync = 0;               // do we wait for vsync?
  int frames, t;                    // for framerate counter
  int i;

  pl_uChar *framebuffer;            // our doublebuffer
  pl_Mat *mat[3+1];                 // our materials, we have 1 extra for null
                                    // termination for plMatMakeOptPal2()
  pl_Cam *cam;                      // our camera
  pl_Obj *land;                     // the land object
  pl_Obj *sky, *sky2;               // the two skies
  int done = 0;

  char pal[768];                    // our palette

  srand(0);                         // initialize rng

  _control87(MCW_EM|PC_24,MCW_EM|MCW_PC);
     // Set the FPU in low precision, no exception mode (REQUIRED)

  printf("Plush 3D Fly v3.0.\n"
         "  %s\n"
         "  %s\n",plVersionString,plCopyrightString);
     // print out startup info

  mouse_init(); // initialize mouse

  printf("\n\nControls:\n"
         "  Mouse: rotate\n"
         "  Mouse buttons: left=move forward, right=move forward fast\n"
         "  s: toggle sky (default on)\n"
         "  -,+: adjust fov (default 90)\n"
         "  [,]: adjust mouse sensitivity\n"
         "  v: toggle vsync (default off)\n\n");

  printf("\nHit any key to begin...");
  getch();
  while (kbhit()) getch(); // make sure keyboard buffer is empty

  set_mode13();  // intialize graphics
  framebuffer = (pl_uChar *) malloc(320*200); // allocate framebuffer
      // create camera
  cam = plCamCreate(320, // width
                    200, // height
                    320.0/200.0*3.0/4.0, // aspect ratio
                    90.0, // fov
                    framebuffer, // framebuffer (our doublebuffer)
                    0);  // zbuffer (not used)
  cam->Y = 800; // move the camera up from the ground

  setup_materials(mat,pal); // intialize materials and palette

  land = setup_landscape(mat[0],mat[1],mat[2]); // create landscape
  sky = land->Children[0]; // unhierarchicalize the sky from the land
  land->Children[0] = 0;
  sky2 = land->Children[1];
  land->Children[1] = 0;

  frames = 0;     // set up for framerate counter
  t = uclock();
  while (!done) { // main loop
    // save time when the frame began, to be used later.
    float prevtime = uclock() / (float) UCLOCKS_PER_SEC;
    frames++; // update for framerate counter

    memset(framebuffer,1,64000); // clear our doublebuffer

    // lots of rendering special casing
    if (draw_sky) { // if we're drawing the sky
      if (cam->Y > 2000) { // if above the sky, only render the skies, with
                           // no far clip plane
        cam->ClipBack = 0.0;
        plRenderBegin(cam);
        plRenderObj(sky);
        plRenderObj(sky2);
      } else {           // otherwise, render the sky (but not the second sky),
                         // and the land, with a far clip plane
        cam->ClipBack = 10000.0;
        plRenderBegin(cam);
        plRenderObj(sky);
        plRenderObj(land);
      }
    } else { // not drawing sky, just render the land
      cam->ClipBack = 10000.0;
      plRenderBegin(cam);
      plRenderObj(land);
    }
    plRenderEnd(); // finish rendering

    // display framerate counter
    plTextPrintf(cam,cam->ClipLeft+5,cam->ClipTop,0.0,156,"%.2f fps",
        (frames/ (float) (uclock() - t)) * (float) UCLOCKS_PER_SEC);
    // display last message
    plTextPrintf(cam,cam->ClipLeft+5,cam->ClipBottom-16,0.0,156,lastmessage);


    if (wait_vsync) vsync(); // wait for vsync
      /* blit to screen. This is pretty darn fast on ip5's but on a 486 you
         would probably be faster doing a plain memcpy(), i.e:
         memcpy((void *) __djgpp_conventional_base+0xA0000,framebuffer,64000);
      */
    fpucopy((void *) __djgpp_conventional_base + 0xA0000,framebuffer,64000/16);

    // We calculate the amount of time in thousanths of seconds this frame took
    prevtime = ((uclock() / (float) UCLOCKS_PER_SEC) - prevtime)*1000.0;
    mouse_get(); // update the mouse
    if (mouse_b & 2) { // if right button hit, we go forward quickly
      cam->X -=
        prevtime*4*sin(cam->Pan*PL_PI/180.0)*cos(cam->Pitch*PL_PI/180.0);
      cam->Z +=
        prevtime*4*cos(cam->Pan*PL_PI/180.0)*cos(cam->Pitch*PL_PI/180.0);
      cam->Y +=
        prevtime*4*sin(cam->Pitch*PL_PI/180.0);
    } else if (mouse_b & 1) { // if left button hit, we go forward slowly
      cam->X -=
        prevtime*2*sin(cam->Pan*PL_PI/180.0)*cos(cam->Pitch*PL_PI/180.0);
      cam->Z +=
        prevtime*2*cos(cam->Pan*PL_PI/180.0)*cos(cam->Pitch*PL_PI/180.0);
      cam->Y +=
        prevtime*2*sin(cam->Pitch*PL_PI/180.0);
    }
    cam->Pitch += (mouse_y*mouse_sens); // update pitch and pan of ship
    cam->Pan -= (mouse_x*mouse_sens);

    if (cam->X > LAND_SIZE/2) cam->X = LAND_SIZE/2; // make sure we don't go
    if (cam->X < -LAND_SIZE/2) cam->X = -LAND_SIZE/2; // too far away
    if (cam->Z > LAND_SIZE/2) cam->Z = LAND_SIZE/2;
    if (cam->Z < -LAND_SIZE/2) cam->Z = -LAND_SIZE/2;
    if (cam->Y < 0) cam->Y = 0;
    if (cam->Y > 8999) cam->Y = 8999;

    while (kbhit()) switch(getch()) { // handle keystrokes
      case 27: done++; break;    // ESC == quit
        // + is for zooming in.
      case '=': case '+': cam->Fov -= 1.0; if (cam->Fov < 1.0) cam->Fov = 1.0;
        sprintf(lastmessage,"FOV: %2.f",cam->Fov);
      break;
        // - is for zooming out
      case '-': cam->Fov += 1.0; if (cam->Fov > 179.0) cam->Fov = 179.0;
        sprintf(lastmessage,"FOV: %2.f",cam->Fov);
      break;
        // [ decreases mouse sensitivity
      case '[': mouse_sens /= 1.1;
        sprintf(lastmessage,"MouseSens: %.3f",mouse_sens);
      break;
        // ] increases mouse sensitivity
      case ']': mouse_sens *= 1.1;
        sprintf(lastmessage,"MouseSens: %.3f",mouse_sens);
      break;
        // v toggles vsync
      case 'v': wait_vsync ^= 1;
        sprintf(lastmessage,"VSync %s",wait_vsync ? "on" : "off");
      break;
        // s toggles sky
      case 's': draw_sky ^= 1;
        sprintf(lastmessage,"Sky %s",draw_sky ? "on" : "off");
      break;
    }
  }
  // set text mode
  set_mode3();
  // clean up
  free(framebuffer);
  plObjDelete(land);
  plObjDelete(sky);
  plObjDelete(sky2);
  plMatDelete(mat[0]);
  plMatDelete(mat[1]);
  plMatDelete(mat[2]);
  plCamDelete(cam);

  printf("This has been a Plush demo app.\n"
         "Visit the Plush 3D homepage at: \n"
         "  http://nullsoft.home.ml.org/plush/\n\n");
}