/* PATCHES FOR ARNOLD LINUX ======================== KDE sound server must be switched off, or configured to use Pulse. */ >In src/cpc/arnold.h /* arnold.h ======== */ >replace void CPC_SetAudioActive(BOOL State); >with /* Set also audio frames per second */ void CPC_SetAudioActive(BOOL State,float fps); /* CPC The next generation - Introduce Warp speed */ void CPC_SetWarpFactor(int); >In src/cpc/arnold.c /* arnold.c ======== */ >replace void CPC_SetAudioActive(BOOL State) >with void CPC_SetAudioActive(BOOL State,float FramesPerSec) >replace AudioEvent_SetFormat(pSoundPlaybackFormat->Frequency, pSoundPlaybackFormat->BitsPerSample, pSoundPlaybackFormat->NumberOfChannels); >with AudioEvent_SetFormat(pSoundPlaybackFormat->Frequency, pSoundPlaybackFormat->BitsPerSample, pSoundPlaybackFormat->NumberOfChannels, FramesPerSec); >replace void CPC_ResetTiming(void) { NopCountToDate = NOPS_PER_MONITOR_SCREEN; } >with /* To introduce Warp speed, we let each Z80 instruction last for fewer Nops: With WarpFactor 1, an emulated Nop lasts 1 original Nop (CPC runs with original speed). With WarpFactor 2, an emulated Nop lasts only 0.5 original Nops (CPC runs 2x as fast). With WarpFactor 3, an emulated Nop lasts only 0.33 original Nops (CPC runs 3x as fast) etc.. */ static int NopCountAcc = 0; /* The accumulated Nop-count */ static int WarpFactor = 1; /* The speedup factor */ void CPC_ResetTiming(void) { NopCountToDate = NOPS_PER_MONITOR_SCREEN; NopCountAcc = 0; } #include void CPC_SetWarpFactor(int NewWarpFactor) { WarpFactor=NewWarpFactor; } >replace void CPCEmulation_Run(void) { BOOL doBreak = FALSE; while (!doBreak) { int NopCount; int LocalNopCountToDate; /* execute the instruction */ #ifdef CPC_NODEBUGGER NopCount = Z80_ExecuteInstruction(); #else NopCount = Debugger_Execute(); #endif /* update CPC nop count - used for other hardware */ CPC_UpdateNopCount(NopCount); >with void CPCEmulation_Run(void) { BOOL doBreak = FALSE; while (!doBreak) { int NopCount; int LocalNopCountToDate; /* execute the instruction */ #ifdef CPC_NODEBUGGER NopCount = Z80_ExecuteInstruction(); #else NopCount = Debugger_Execute(); #endif /* Accumulate the Nop counts */ NopCountAcc += NopCount; /* See if we accumulated enough */ NopCount = 0; while (NopCountAcc>=WarpFactor) { NopCount++; NopCountAcc-=WarpFactor; } /* update CPC nop count - used for other hardware */ CPC_UpdateNopCount(NopCount); >In src/cpc/audioevent.h /* audioevent.h ============ */ >replace void AudioEvent_SetFormat(int SampleRate, int SampleBits, int SampleChannels); >with void AudioEvent_SetFormat(int SampleRate, int SampleBits, int SampleChannels, float FramesPerSec); >In src/cpc/audioevent.c /* audioevent.c ============ */ >replace void AudioEvent_SetFormat(int SampleRate, int SampleBits, int SampleChannels) { AudioEvent_SampleBits = SampleBits; AudioEvent_SampleChannels = SampleChannels; Audio_Init(SampleRate, SampleBits, SampleChannels); } >with void AudioEvent_SetFormat(int SampleRate, int SampleBits, int SampleChannels, float FramesPerSec) { AudioEvent_SampleBits = SampleBits; AudioEvent_SampleChannels = SampleChannels; Audio_Init(SampleRate, SampleBits, SampleChannels, FramesPerSec); } >replace void Audio_Init(int newFrequency, int newBitsPerSample, int newNoOfChannels); >with void Audio_Init(int newFrequency, int newBitsPerSample, int newNoOfChannels, float FramesPerSec); >replace void Audio_Init(int newFrequency, int newBitsPerSample, int newNoOfChannels) { SampleRate = newFrequency; BitsPerSample = newBitsPerSample; NoOfChannels = newNoOfChannels; ScreenRefreshFrequency = 50.08f; >with void Audio_Init(int newFrequency, int newBitsPerSample, int newNoOfChannels, float FramesPerSec) { SampleRate = newFrequency; BitsPerSample = newBitsPerSample; NoOfChannels = newNoOfChannels; if (FramesPerSec>0) { ScreenRefreshFrequency = FramesPerSec; } >In src/unix/display.h /* display.h ========= */ >after void sdl_Throttle(void); >insert int sdl_RefreshRate(void); void sdl_SetFPS(int); >In src/unix/keyboard_sdl.c /* keyboard_sdl.c ============== */ >after int keyUnicodeFlag = 0; >insert int joyemulated = 0; /* Flag if joystick is emulated with cursor keys+space */ >after } else if (keycode == SDLK_F4 && theEvent->type == SDL_KEYDOWN ) { quit(); >insert } else if (keycode == SDLK_F5 && theEvent->type == SDL_KEYDOWN ) { /* F5 - turn Joystick emulation on/off */ joyemulated^=1; fprintf(stderr,"Joystick emulation with cursor keys and space: %d\n",joyemulated); } else if (keycode == SDLK_F6 && theEvent->type == SDL_KEYDOWN ) { /* F6 - Reduce Warp factor */ cpc_warpfactor--; if (cpc_warpfactor<1) cpc_warpfactor=1; CPC_SetWarpFactor(cpc_warpfactor); sdl_warpfacdisptime=100; fprintf(stderr,"CPC now running at warp %d.\n",cpc_warpfactor); } else if (keycode == SDLK_F7 && theEvent->type == SDL_KEYDOWN ) { /* F7 - Increase Warp factor */ cpc_warpfactor++; if (cpc_warpfactor>CPC_WARPFACTORMAX) cpc_warpfactor=CPC_WARPFACTORMAX; CPC_SetWarpFactor(cpc_warpfactor); sdl_warpfacdisptime=100; fprintf(stderr,"CPC now running at warp %d.\n",cpc_warpfactor); #ifdef HAVE_GL } else if (fullscreen && (keysym->mod&KMOD_CTRL) && keycode == SDLK_UP && theEvent->type == SDL_KEYDOWN ) { /* Ctrl+Cursor Up: Zoom away */ sdl_zoomspeed=1; } else if (fullscreen && (keysym->mod&KMOD_CTRL) && keycode == SDLK_DOWN && theEvent->type == SDL_KEYDOWN ) { /* Ctrl+Cursor Down: Zoom closer */ sdl_zoomspeed=-1; } else if (theEvent->type == SDL_KEYUP && ((keycode == SDLK_UP && sdl_zoomspeed>0)||(keycode == SDLK_DOWN && sdl_zoomspeed<0))) { /* Stop zooming */ sdl_zoomspeed=0; #endif } else if (joyemulated && keycode == SDLK_UP) { /* Joystick up */ if (theEvent->type == SDL_KEYDOWN) { CPC_SetKey(CPC_KEY_JOY_UP); CPC_ClearKey(CPC_KEY_JOY_DOWN); } else CPC_ClearKey(CPC_KEY_JOY_UP); } else if (joyemulated && keycode == SDLK_DOWN) { /* Joystick down */ if (theEvent->type == SDL_KEYDOWN) { CPC_SetKey(CPC_KEY_JOY_DOWN); CPC_ClearKey(CPC_KEY_JOY_UP); } else CPC_ClearKey(CPC_KEY_JOY_DOWN); } else if (joyemulated && keycode == SDLK_LEFT) { /* Joystick left */ if (theEvent->type == SDL_KEYDOWN) { CPC_SetKey(CPC_KEY_JOY_LEFT); CPC_ClearKey(CPC_KEY_JOY_RIGHT); } else CPC_ClearKey(CPC_KEY_JOY_LEFT); } else if (joyemulated && keycode == SDLK_RIGHT) { /* Joystick right */ if (theEvent->type == SDL_KEYDOWN) { CPC_SetKey(CPC_KEY_JOY_RIGHT); CPC_ClearKey(CPC_KEY_JOY_LEFT); } else CPC_ClearKey(CPC_KEY_JOY_RIGHT); } else if (joyemulated && keysym->scancode == 0x73) { /* Joystick button 1, needs to use scancode, because keycode is 0x134 for both (SDL bug) */ if (theEvent->type == SDL_KEYDOWN) CPC_SetKey(CPC_KEY_JOY_FIRE1); else CPC_ClearKey(CPC_KEY_JOY_FIRE1); } else if (joyemulated && keysym->scancode == 0x40) { /* Joystick button 2, needs to use scancode, because keycode is 0x134 for both (SDL bug) */ if (theEvent->type == SDL_KEYDOWN) CPC_SetKey(CPC_KEY_JOY_FIRE2); else CPC_ClearKey(CPC_KEY_JOY_FIRE2); >In src/unix/main.c /* main.c ====== */ >after printf("-frameskip = specify frame skip (0-5)\n"); >insert printf("-fps = specify frames per second\n"); printf("-sync = try to synchronize with screen refresh rate\n"); #ifdef HAVE_GL printf("-opengl = use OpenGL for smooth zooming in fullscreen mode\n"); #endif >after {"frameskip", 1, 0, 'f'}, >insert {"fps", 1, 0, 'z'}, {"sync", 0, 0, 'y'}, #ifdef HAVE_GL {"opengl", 1, 0, 'g'}, #endif >after int digit_optind = 0; >insert /* Default is 50 frames per second without sync to screen refresh rate */ int fps = 50; int sync = 0; int refresh; >after case 'f': frameskip = optarg; break; >insert case 'y': /* Activate sync to screen refresh rate */ sync=1; #ifdef HAVE_GL /* Activate sync on nVIDIA chips */ putenv("__GL_SYNC_TO_VBLANK=1"); #endif break; case 'z': /* Set refresh rate in Hz directly */ fps = atoi(optarg); break; >replace #ifdef HAVE_GTK fprintf(stderr, "Initializing GTK+\n"); gtkui_init(argc, argv); #endif #ifdef HAVE_SDL fprintf(stderr, "Initializing SDL\n"); if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO|SDL_INIT_TIMER |SDL_INIT_JOYSTICK) < 0 ) { fprintf(stderr, "SDL could not be initialized: %s\n", SDL_GetError()); exit(1); } sdl_InitialiseKeyboardMapping(0); sdl_InitialiseJoysticks(); atexit(SDL_Quit); #endif Host_InitDriveLEDIndicator(); Render_SetDisplayWindowed(); #ifdef HAVE_SDL if (doubled) { #ifdef HAVE_GTK gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON (btn_double), TRUE ); #else sdl_SetDoubled(doubled); #endif } if (fullscreen) { toggleFullscreenLater = TRUE; } if (kbd != -1) sdl_InitialiseKeyboardMapping(kbd); #endif printf("%s", Messages[76]); CPC_SetAudioActive(TRUE); printf("%s", Messages[77]); >with #ifdef HAVE_SDL fprintf(stderr, "Initializing SDL\n"); if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO|SDL_INIT_TIMER |SDL_INIT_JOYSTICK|SDL_INIT_NOPARACHUTE) < 0 ) { fprintf(stderr, "SDL could not be initialized: %s\n", SDL_GetError()); exit(1); } sdl_InitialiseKeyboardMapping(0); sdl_InitialiseJoysticks(); atexit(SDL_Quit); #endif Host_InitDriveLEDIndicator(); Render_SetDisplayWindowed(); /* This hardly ever works, because SDL_Flip is often not capable of waiting for a vertical retrace */ if (sync) { /* Synchronize to vertical retrace */ #ifndef HAVE_SDL fprintf(stderr,"SDL must be present to enable vertical sync.\n"); #else refresh = sdl_RefreshRate(); if (!refresh) fprintf(stderr,"Refresh rate cannot be determined, using %d FPS.\n",fps); else { fps = refresh; fprintf(stderr,"Running Arnold with screen refresh rate of %d FPS.\n",fps); } #endif } /* Set refresh rate */ fprintf(stderr,"Running emulation with %d fps\n",fps); #ifdef HAVE_SDL sdl_SetFPS(fps); #endif /* Set also fps in Arnold */ CPC_SetAudioActive(TRUE,fps); printf("%s", Messages[77]); #ifdef HAVE_SDL if (doubled) { #ifdef HAVE_GTK gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON (btn_double), TRUE ); #else sdl_SetDoubled(doubled); #endif } if (fullscreen) { toggleFullscreenLater = TRUE; } if (kbd != -1) sdl_InitialiseKeyboardMapping(kbd); #endif printf("%s", Messages[76]); >replace #ifdef HAVE_GTK gtkui_run(); #else >with #ifdef HAVE_GTK /*while (1) { CPCEmulation_Run(); SDL_Delay(20); }*/ /* gtkui_init must be called after CPC_SetAudioActive */ gtkui_init(argc, argv); gtkui_run(); #else >In src/unix/display_sdl.c /* display_sdl.c ============= */ >replace void sdl_SetDisplay(int Width, int Height, int Depth, BOOL wantfullscreen) { fullscreen = wantfullscreen; fprintf(stderr, Messages[106], Width, Height, Depth); if ( fullscreen ) mode |= SDL_FULLSCREEN; else mode &= ~SDL_FULLSCREEN; screen = SDL_SetVideoMode(Width, Height, Depth, mode); if ( screen == NULL ) { fprintf(stderr, Messages[107], Width, Height, Depth, SDL_GetError()); exit(1); } } >with #include #include #define CPC_WARPFACTORMAX 16 /* Maximum allowed warp speed factor */ int cpc_warpfactor=1; /* Current CPC warp speed factor */ #ifdef HAVE_GL #include #define SDL_SCRLENX 384 /* Width and height of the CPC screen drawn by Arnold */ #define SDL_SCRLENY 272 #define SDL_TEXLENX 512 /* Width and height of the corresponding texture, must be a power of 2 */ #define SDL_TEXLENY 512 #define SDL_TEXSCALE 5 /* Scaling factor for CPC screen texture to allow zooming in */ #define SDL_CLIPZ 100000 /* Distance of the far Z-clipping plane */ #ifdef MACOS /* IN MACOSX, THIS IS MUCH FASTER */ #define GL_BGRAFORMAT GL_UNSIGNED_INT_8_8_8_8_REV #else /* IN LINUX (ATI RADEON) THIS IS MUCH FASTER */ #define GL_BGRAFORMAT GL_UNSIGNED_BYTE #endif int sdl_eyedis; /* Distance between eye and viewplane */ int sdl_scrposz; /* The screen Z-position (zoom) */ int sdl_zoomspeed; /* Current speed of window zooming with Ctrl+Cursor Up/Down */ int sdl_warpfacdisptime; /* Number of screen updates left until the warp factor is no longer displayed */ GLuint sdl_texture; /* Texture with CPC screen */ SDL_Surface *sdl_texbuffer; /* Buffer to store texture data before upload */ #endif void sdl_SetDisplay(int Width, int Height, int Depth, BOOL wantfullscreen) { int i,accepted,format; SDL_SysWMinfo wm; fullscreen = wantfullscreen; fprintf(stderr, Messages[106], Width, Height, Depth); if ( !fullscreen ) { mode &= ~SDL_OPENGL; mode &= ~SDL_FULLSCREEN; } else { /* Fullscreen requested */ mode |= SDL_FULLSCREEN; #ifdef HAVE_GL if (sdl_texbuffer) { /* Delete previous texture */ glDeleteTextures(1,&sdl_texture); SDL_FreeSurface(sdl_texbuffer); sdl_texbuffer=NULL; } mode |= SDL_OPENGL; SDL_GL_SetAttribute(SDL_GL_RED_SIZE,8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,8); SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE,8); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,0); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1); /* SYNC TO VERTICAL RETRACE */ /* 16 = SDL_GL_SWAP_CONTROL, WHICH IS NOT IN THE OLD WINDOWS SDL HEADERS */ SDL_GL_SetAttribute(16,1); /* Get native screen resolution */ SDL_VERSION(&wm.version); if (SDL_GetWMInfo(&wm)>0) { Width=DisplayWidth(wm.info.x11.display,DefaultScreen(wm.info.x11.display)); Height=DisplayHeight(wm.info.x11.display,DefaultScreen(wm.info.x11.display)); fprintf(stderr,"Using native fullscreen resolution %dx%d.\n",Width,Height); } #endif } screen = SDL_SetVideoMode(Width, Height, Depth, mode); if ( screen == NULL ) { fprintf(stderr, Messages[107], Width, Height, Depth, SDL_GetError()); exit(1); } #ifdef HAVE_GL if (fullscreen) { /* Setup OpenGL parameters */ glShadeModel(GL_SMOOTH); glDisable(GL_CULL_FACE); glPixelStorei(GL_UNPACK_ALIGNMENT,1); /* The three OpenGL transformations */ glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); /* Set distance between eye and viewplane, simply the width of the screen */ sdl_eyedis=Width; /* The CPC screen is drawn at five times this depth by default, so that it can zoom in closer before being clipped. sdl_eyedis-1 is for nVIDIA cards which clip too soon */ sdl_scrposz=sdl_eyedis*SDL_TEXSCALE; glFrustum(-Width*0.5,Width*0.5,-Height*0.5,Height*0.5,sdl_eyedis-1,sdl_eyedis+SDL_CLIPZ); //printf("Frustum=%f,%f,%f,%f,%d,%d\n",-Width*0.5,Width*0.5,-Height*0.5,Height*0.5,sdl_eyedis,sdl_eyedis+SDL_CLIPZ); glViewport(0,0,(GLsizei)Width,(GLsizei)Height); glClearColor(0,0,0,0); glDrawBuffer(GL_FRONT); glClear(GL_COLOR_BUFFER_BIT); glDrawBuffer(GL_BACK); glClear(GL_COLOR_BUFFER_BIT); /* Define texture which will contain the CPC screen */ /* Warning: The order of the RGB components is flipped to BGR to match texture upload */ sdl_texbuffer=SDL_CreateRGBSurface(SDL_SWSURFACE,SDL_TEXLENX,SDL_TEXLENY,32,0x00ff0000,0x0000ff00,0x000000ff,0xff000000); glGenTextures(1,&sdl_texture); glBindTexture(GL_TEXTURE_2D,sdl_texture); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); /* Determine best format for textures and upload */ format=GL_RGBA8; do { glTexImage2D(GL_PROXY_TEXTURE_2D,0,format,SDL_TEXLENX,SDL_TEXLENY,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_INTERNAL_FORMAT,&accepted); if (!accepted) { if (format==GL_RGBA8) format=GL_RGB5_A1; else { fprintf(stderr,"Cannot allocate OpenGL texture"); exit(1); } } } while (!accepted); glTexImage2D(GL_TEXTURE_2D,0,format,SDL_TEXLENX,SDL_TEXLENY,0,GL_RGBA,GL_UNSIGNED_BYTE,sdl_texbuffer->pixels); } #endif } >replace } else { sdl_SetDisplayWindowed(screen->w,screen->h, screen->format->BitsPerPixel); } >with } else { #ifndef HAVE_GL sdl_SetDisplayWindowed(screen->w,screen->h, screen->format->BitsPerPixel); #else /* In OpenGL mode, we work with the native screen resolution, which we don't want in window mode */ sdl_SetDisplayWindowed(SDL_SCRLENX*scale,SDL_SCRLENY*scale,screen->format->BitsPerPixel); #endif } >replace #define FRAMES_PER_SEC 50 >with int sdl_fps = 50; /* Set SDL frames per second */ void sdl_SetFPS(int fps) { sdl_fps=fps; } >replace next_tick = next_tick + (1000/FRAMES_PER_SEC); } else { next_tick = this_tick + (1000/FRAMES_PER_SEC); >with next_tick = next_tick + (1000/sdl_fps); } else { next_tick = this_tick + (1000/sdl_fps); >replace #if 0 #ifndef BUSYWAIT double delta_time() { static struct timeval t1, t2; double dt; gettimeofday(&t1,NULL); dt=(t1.tv_sec - t2.tv_sec)+(t1.tv_usec - t2.tv_usec)/1000000.0; /* 1000000 microseconds in a second... */ //printf("\ntime: %i %i %i %i delta: %f\n",t1.tv_sec, t2.tv_sec, t1.tv_usec, t2.tv_usec, dt); memcpy( &t2, &t1, sizeof(t2) ); return dt; } #else unsigned long timeGetTime() { static struct timeval t1; gettimeofday(&t1,NULL); return (t1.tv_sec<<6|t1.tv_usec); } #endif #endif >with /* Get elapsed time in microseconds Works correctly for time intervals up to ~4000 seconds */ unsigned long sdl_GetMicrosecondsDelta() { static struct timeval t1, t2; unsigned long dt; gettimeofday(&t1,NULL); dt=(t1.tv_sec - t2.tv_sec)*1000000+(t1.tv_usec - t2.tv_usec); /* 1000000 microseconds in a second... */ //printf("\ntime: %i %i %i %i delta: %f\n",t1.tv_sec, t2.tv_sec, t1.tv_usec, t2.tv_usec, dt); memcpy( &t2, &t1, sizeof(t2) ); return dt; } /* unsigned long long sdl_GetMicroseconds() { struct timeval t1; gettimeofday(&t1,NULL); return (t1.tv_sec*1000000+t1.tv_usec); } */ #define SDL_REFRESHMAX 200 /* Determine current screen refresh rate This only works if the video driver has sync to vblank enabled. Returns 0 if unsuccessful. */ int sdl_RefreshRate(void) { int i,refresh; int refreshguess[SDL_REFRESHMAX]; memset(refreshguess,0,sizeof(refreshguess)); sdl_GetMicrosecondsDelta(); /* We need ~70 tries */ for (i=0;i<70;i++) { SDL_Flip( screen ); refresh=1e6/sdl_GetMicrosecondsDelta(); //printf("Got refresh rate %d\n",refresh); if (refreshreplace void sdl_GetGraphicsBufferInfo(GRAPHICS_BUFFER_INFO *pBufferInfo) { pBufferInfo->pSurface = screen->pixels; pBufferInfo->Width = screen->w; pBufferInfo->Height = screen->h; pBufferInfo->Pitch = screen->pitch; //printf("get buffer info\r\n"); //printf("W: %d H: %d P: %d\r\n",pBufferInfo->Width, pBufferInfo->Height, //pBufferInfo->Pitch); } BOOL sdl_LockGraphicsBuffer(void) { if (SDL_LockSurface(screen) == 0) return TRUE; else return FALSE; } void sdl_UnlockGraphicsBuffer(void) { SDL_UnlockSurface(screen); } >with void sdl_GetGraphicsBufferInfo(GRAPHICS_BUFFER_INFO *pBufferInfo) { SDL_Surface *buffer; buffer=screen; #ifdef HAVE_GL if (fullscreen) buffer=sdl_texbuffer; #endif pBufferInfo->pSurface = buffer->pixels; pBufferInfo->Width = buffer->w; pBufferInfo->Height = buffer->h; pBufferInfo->Pitch = buffer->pitch; //printf("get buffer info\r\n"); //printf("W: %d H: %d P: %d\r\n",pBufferInfo->Width, pBufferInfo->Height, //pBufferInfo->Pitch); } BOOL sdl_LockGraphicsBuffer(void) { #ifdef HAVE_GL if (fullscreen) return TRUE; #endif if (SDL_LockSurface(screen) == 0) return TRUE; else return FALSE; } void sdl_UnlockGraphicsBuffer(void) { #ifdef HAVE_GL unsigned char coltab[4]; int i,j,sign; Uint32 color; Uint32 *pixels; float posx,posy,startx,starty,endx,endy,nativeratio,cpcratio,f; SDL_PixelFormat *format; if (fullscreen) { /* Calculate new Z-position of CPC window (can be zoomed with Ctrl+cursor keys) */ sdl_scrposz+=sdl_zoomspeed*5*SDL_TEXSCALE; if (sdl_scrposzsdl_eyedis*2*SDL_TEXSCALE) sdl_scrposz=sdl_eyedis*2*SDL_TEXSCALE; /* Determine position of CPC screen */ nativeratio=(float)screen->w/screen->h; cpcratio=(float)SDL_SCRLENX/SDL_SCRLENY; if (nativeratio>cpcratio) { /* Native screen is wider than CPC screen */ posy=screen->h*SDL_TEXSCALE*0.5; posx=posy*cpcratio; } else { /* Native screen is higher than CPC screen */ posx=screen->w*SDL_TEXSCALE*0.5; posy=posx/cpcratio; } /* Determine background color: See if three pixel columns at the left and right side of the CPC screen all have the same color (no overscan) */ color=*(Uint32*)sdl_texbuffer->pixels; for (i=0;i<2;i++) { for (j=0;jpixels+j*sdl_texbuffer->pitch)+i*(SDL_SCRLENX-3); if (pixels[0]!=color||pixels[1]!=color||pixels[2]!=color) { /* Color differs */ color=0; break; } } } /* Clear screen */ glBegin(GL_QUADS); SDL_GetRGBA(color,sdl_texbuffer->format,coltab,coltab+1,coltab+2,coltab+3); glColor3f(coltab[0]/255.,coltab[1]/255.,coltab[2]/255.); glVertex3f(screen->w,screen->h,-sdl_eyedis); glVertex3f(-screen->w,screen->h,-sdl_eyedis); glVertex3f(-screen->w,-screen->h,-sdl_eyedis); glVertex3f(screen->w,-screen->h,-sdl_eyedis); glEnd(); /* Upload texture */ //printf("TexSubImage %d...\n",sdl_texture); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,sdl_texture); glPixelStorei(GL_UNPACK_ROW_LENGTH,SDL_TEXLENX); glTexSubImage2D(GL_TEXTURE_2D,0,0,0,SDL_SCRLENX,SDL_SCRLENY,GL_BGRA,GL_BGRAFORMAT,sdl_texbuffer->pixels); /* Draw texture, clipping 1 pixel on each side to prevent the linear texture filter from accessing pixels outside the CPC screen */ startx=1./SDL_TEXLENX; starty=1./SDL_TEXLENY; endx=(float)(SDL_SCRLENX-1)/SDL_TEXLENX; endy=(float)(SDL_SCRLENY-1)/SDL_TEXLENY; glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE); glBegin(GL_QUADS); glTexCoord2f(endx,starty); glVertex3f(posx,posy,-sdl_scrposz); glTexCoord2f(startx,starty); glVertex3f(-posx,posy,-sdl_scrposz); glTexCoord2f(startx,endy); glVertex3f(-posx,-posy,-sdl_scrposz); glTexCoord2f(endx,endy); glVertex3f(posx,-posy,-sdl_scrposz); glEnd(); glDisable(GL_TEXTURE_2D); if (sdl_warpfacdisptime>0) { /* The warp factor should be displayed on screen */ sdl_warpfacdisptime--; glBegin(GL_QUADS); startx=screen->w*0.45; endx=screen->w*0.48; for (i=0;ih*(-0.45+i*0.05); endy=screen->h*(-0.45+i*0.05-0.03); f=(float)i/CPC_WARPFACTORMAX; glColor3f(1.0*f,1.0*(1-f),0); glVertex3f(endx,starty,-sdl_eyedis); glVertex3f(startx,starty,-sdl_eyedis); glVertex3f(startx,endy,-sdl_eyedis); glVertex3f(endx,endy,-sdl_eyedis); } glEnd(); } } #endif SDL_UnlockSurface(screen); } >replace void sdl_SwapGraphicsBuffers(void) { if ( scale == 2 ) sdl_DoubleGraphicsBuffer(); //SDL_UpdateRects(screen,1,&screen->clip_rect); SDL_Flip( screen ); } >with void sdl_SwapGraphicsBuffers(void) { #ifdef HAVE_GL if (fullscreen) { SDL_GL_SwapBuffers(); return; } #endif if ( scale == 2 ) sdl_DoubleGraphicsBuffer(); //SDL_UpdateRects(screen,1,&screen->clip_rect); SDL_Flip( screen ); } >In src/unix/gtkui.c /* gtkui.c ======= */ >replace CPC_SetAudioActive(state); >with /* fps=0 keeps the previous value */ CPC_SetAudioActive(state,0); >In src/unix/ifacegen.c /* ifacegen.c ========== */ >replaceall return bStatus; >with /* This fixes a segfault */ return bStatus==ARNOLD_STATUS_OK; >In src/unix/sound.c /* sound.c ======= */ >after #include "alsasound-common.h" >insert #include "osssound.h" >replace case SOUND_PLUGIN_OSS: return TRUE; >with case SOUND_PLUGIN_OSS: return oss_Throttle(); >replace #ifdef HAVE_ALSA if (alsa_AudioPlaybackPossible()) { return SOUND_PLUGIN_ALSA; } #endif if (oss_AudioPlaybackPossible()) { return SOUND_PLUGIN_OSS; } >with if (oss_AudioPlaybackPossible()) { return SOUND_PLUGIN_OSS; } #ifdef HAVE_ALSA if (alsa_AudioPlaybackPossible()) { return SOUND_PLUGIN_ALSA; } #endif >In src/unix/alsasound-common.c /* alsasound-common.c ================== */ >delete printf("xrun_recovery\n"); >end