Update of /cvsroot/arcem/arcem/X In directory vz-cvs-4.sog:/tmp/cvs-serv17456/arcem/X
Modified Files: ControlPane.c DispKbd.c filecalls.c platform.h sound.c Added Files: pseudo.c true.c Log Message: Merge arcem-fast to trunk Index: sound.c =================================================================== RCS file: /cvsroot/arcem/arcem/X/sound.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- sound.c 29 Jan 2005 17:18:20 -0000 1.1 +++ sound.c 12 May 2012 17:34:51 -0000 1.2 @@ -11,93 +11,174 @@ #include "../armdefs.h" #include "../arch/sound.h" +#include "../arch/displaydev.h" +#include "../armemu.h" -static unsigned long format = AFMT_S16_LE; -static unsigned long channels = 2; -/*static unsigned long bits = 16;*/ -static unsigned long sampleRate = 0; - -static unsigned long bufferSize = 0; - -/*static unsigned long numberGot = 0;*/ - -static unsigned long bufferRead = 0; -static unsigned long bufferWrite = 0; - -/* This is how many 16 byte blocks to get before leaving - * sound_poll to return to the emulator */ -static unsigned long blocksAtATime = 1; -/* This is how many 16 byte blocks should be collected before - * calling write(), so this controls the size of the buffer. */ -static unsigned long numberOfFills = 100; - -/* This is the size of the gap between sound_poll doing something. */ -static unsigned long delayTotal = 100; -static unsigned long delayProgress = 0; +static uint32_t format = AFMT_S16_LE; +static uint32_t channels = 2; +static uint32_t sampleRate = 44100; static int soundDevice; -static SoundData *buffer = NULL; +/* Threading currently doesn't work very well - no priority control is in place, so the sound thread hardly ever gets any CPU time */ +//#define SOUND_THREAD + +#ifdef SOUND_THREAD static pthread_t thread; static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; -void -sound_poll(void) +#define BUFFER_SAMPLES (16384) /* 8K stereo pairs */ + +SoundData sound_buffer[BUFFER_SAMPLES]; +volatile int32_t sound_buffer_in=BUFFER_SAMPLES; /* Number of samples we've placed in the buffer */ +volatile int32_t sound_buffer_out=0; /* Number of samples read out by the sound thread */ +static const int32_t sound_buff_mask=BUFFER_SAMPLES-1; +#else +SoundData sound_buffer[256*2]; /* Must be >= 2*Sound_BatchSize! */ +#endif + +SoundData *Sound_GetHostBuffer(int32_t *destavail) { - static unsigned long localBufferWrite = 0; +#ifdef SOUND_THREAD + /* Work out how much space is available until next wrap point, or we start overwriting data */ + pthread_mutex_lock(&mut); + int32_t local_buffer_in = sound_buffer_in; + int32_t used = local_buffer_in-sound_buffer_out; + pthread_mutex_unlock(&mut); + int32_t ofs = local_buffer_in & sound_buff_mask; + int32_t buffree = BUFFER_SAMPLES-MAX(ofs,used); + *destavail = buffree>>1; + return sound_buffer + ofs; +#else + /* Just assume we always have enough space for the max batch size */ + *destavail = sizeof(sound_buffer)/(sizeof(SoundData)*2); + return sound_buffer; +#endif +} - delayProgress++; - if (delayProgress >= delayTotal) { - int i; +void Sound_HostBuffered(SoundData *buffer,int32_t numSamples) +{ + numSamples <<= 1; +#ifdef SOUND_THREAD + pthread_mutex_lock(&mut); + int32_t local_buffer_in = sound_buffer_in; + int32_t used = local_buffer_in-sound_buffer_out; + pthread_mutex_unlock(&mut); + int32_t ofs = local_buffer_in & sound_buff_mask; - /*bufferWrite = (numberGot + i) * 16 * 2);*/ + local_buffer_in += numSamples; + + if(buffree == numSamples) + { + fprintf(stderr,"*** sound overflow! ***\n"); + if(Sound_FudgeRate < -10) + Sound_FudgeRate = Sound_FudgeRate/2; + else + Sound_FudgeRate+=10; + } + else if(!used) + { + fprintf(stderr,"*** sound underflow! ***\n"); + if(Sound_FudgeRate > 10) + Sound_FudgeRate = Sound_FudgeRate/2; + else + Sound_FudgeRate-=10; + } + else if(used < BUFFER_SAMPLES/4) + { + Sound_FudgeRate--; + } + else if(buffree < BUFFER_SAMPLES/4) + { + Sound_FudgeRate++; + } + else if(Sound_FudgeRate) + { + /* Bring the fudge value back towards 0 until we go out of the comfort zone */ + Sound_FudgeRate += (Sound_FudgeRate>0?-1:1); + } - for (i = 0; i < blocksAtATime; i++) { - /* *Important*, you must respect whether sound dma - * is enabled or not at all times otherwise sound - * will come out wrong. - */ - /*if( SoundDMAFetch(buffer + ((numberGot + i) * 16 * 2)) == 1 ) return; */ - if (SoundDMAFetch(buffer + localBufferWrite) == 1) { - return; - } - } + pthread_mutex_lock(&mut); + sound_buffer_in = local_buffer_in; + pthread_mutex_unlock(&mut); + pthread_cond_broadcast(&cond); - localBufferWrite += (blocksAtATime * 16 * 2); - if (localBufferWrite >= (bufferSize / sizeof(SoundData))) { - localBufferWrite = 0; + pthread_yield(); +#else + audio_buf_info buf; + if (ioctl(soundDevice, SOUND_PCM_GETOSPACE, &buf) != -1) { + /* Adjust fudge rate based around how much buffer space is available + We aim for the buffer to be somewhere between 1/4 and 3/4 full, but don't + explicitly set the buffer size, so we're at the mercy of the sound system + in terms of how much lag there'll be */ + int32_t bufsize = buf.fragsize*buf.fragstotal; + int32_t buffree = buf.bytes/sizeof(SoundData); + int32_t used = (bufsize-buf.bytes)/sizeof(SoundData); + int32_t stepsize = Sound_DMARate>>2; + bufsize /= sizeof(SoundData); + if(numSamples > buffree) + { + fprintf(stderr,"*** sound overflow! %d %d %d %d ***\n",numSamples-buffree,ARMul_EmuRate,Sound_FudgeRate,Sound_DMARate); + numSamples = buffree; /* We could block until space is available, but I'm woried we'd get stuck blocking forever because the FudgeRate increase wouldn't compensate for the ARMul cycles lost due to blocking */ + if(Sound_FudgeRate < -stepsize) + Sound_FudgeRate = Sound_FudgeRate/2; + else + Sound_FudgeRate+=stepsize; } - - if (pthread_mutex_trylock(&mut) == 0) { - bufferWrite = localBufferWrite; - pthread_mutex_unlock(&mut); - pthread_cond_broadcast(&cond); + else if(!used) + { + fprintf(stderr,"*** sound underflow! %d %d %d ***\n",ARMul_EmuRate,Sound_FudgeRate,Sound_DMARate); + if(Sound_FudgeRate > stepsize) + Sound_FudgeRate = Sound_FudgeRate/2; + else + Sound_FudgeRate-=stepsize; + } + else if(used < bufsize/4) + { + Sound_FudgeRate-=stepsize>>4; + } + else if(buffree < bufsize/4) + { + Sound_FudgeRate+=stepsize>>4; + } + else if(Sound_FudgeRate) + { + /* Bring the fudge value back towards 0 until we go out of the comfort zone */ + Sound_FudgeRate += (Sound_FudgeRate>0?-1:1); } - delayProgress = 0; } + + write(soundDevice,buffer,numSamples*sizeof(SoundData)); +#endif } +#ifdef SOUND_THREAD static void * sound_writeThread(void *arg) { + int32_t local_buffer_out = sound_buffer_out; for (;;) { - int y; + int32_t avail; pthread_mutex_lock(&mut); - y = bufferWrite; + sound_buffer_out = local_buffer_out; + avail = sound_buffer_in-local_buffer_out; pthread_mutex_unlock(&mut); - if (bufferRead != y) { - if (y < bufferRead) { - y = bufferSize / sizeof(SoundData); - } - write(soundDevice, buffer + bufferRead, - (y - bufferRead) * sizeof(SoundData)); - bufferRead = y; - if (bufferRead >= (bufferSize / sizeof(SoundData))) { - bufferRead = 0; + printf("%d\n",avail); + if (avail) { + int32_t ofs = local_buffer_out & sound_buff_mask; + + if(ofs + avail > BUFFER_SAMPLES) { + /* We're about to wrap */ + avail = BUFFER_SAMPLES-ofs; } + + write(soundDevice, sound_buffer + ofs, + avail * sizeof(SoundData)); + + local_buffer_out += avail; } else { pthread_mutex_lock(&mut); pthread_cond_wait(&cond, &mut); @@ -107,11 +188,12 @@ return NULL; } +#endif int -sound_init(void) +Sound_InitHost(ARMul_State *state) { - if ((soundDevice = open("/dev/dsp", O_CREAT | O_WRONLY )) < 0) { + if ((soundDevice = open("/dev/dsp", O_WRONLY )) < 0) { fprintf(stderr, "Could not open audio device /dev/dsp\n"); return -1; } @@ -137,42 +219,33 @@ } if (ioctl(soundDevice, SOUND_PCM_WRITE_RATE, &sampleRate) == -1) { - fprintf(stderr, "Could not set initial sample rate\n"); + fprintf(stderr, "Could not set sample rate\n"); return -1; } - bufferSize = numberOfFills * 16 * 2 * sizeof(SoundData); - buffer = malloc(bufferSize); - if (!buffer) { - fprintf(stderr, "sound_init(): Out of memory\n"); - exit(EXIT_FAILURE); + if (ioctl(soundDevice, SOUND_PCM_READ_RATE, &sampleRate) == -1) { + fprintf(stderr, "Could not read sample rate\n"); + return -1; } - pthread_create(&thread, NULL, sound_writeThread, 0); + /* Check that GETOSPACE is supported */ + audio_buf_info buf; + if (ioctl(soundDevice, SOUND_PCM_GETOSPACE, &buf) == -1) { + fprintf(stderr,"Could not read output space\n"); + return -1; + } + fprintf(stderr,"Sound buffer params: frags %d total %d size %d bytes %d\n",buf.fragments,buf.fragstotal,buf.fragsize,buf.bytes); - return 0; -} + eSound_StereoSense = Stereo_LeftRight; -/** - * sound_setSampleRate - * - * Set the sample rate of sound, using - * the period specified in microseconds. - * - * @param period period of sample in microseconds - */ -void -sound_setSampleRate(unsigned long period) -{ - /* freq = 1 / (period * 10^-6) */ - if (period != 0) { - sampleRate = 1000000 / period; - } else { - sampleRate = 44100; - } + /* Use a decent batch size */ + Sound_BatchSize = 256; - printf("asked to set sample rate to %lu\n", sampleRate); - ioctl(soundDevice, SOUND_PCM_WRITE_RATE, &sampleRate); - ioctl(soundDevice, SOUND_PCM_READ_RATE, &sampleRate); - printf("set sample rate to %lu\n", sampleRate); + Sound_HostRate = sampleRate<<10; + +#ifdef SOUND_THREAD + pthread_create(&thread, NULL, sound_writeThread, 0); +#endif + + return 0; } Index: filecalls.c =================================================================== RCS file: /cvsroot/arcem/arcem/X/filecalls.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- filecalls.c 30 Jan 2005 15:59:27 -0000 1.1 +++ filecalls.c 12 May 2012 17:34:51 -0000 1.2 @@ -23,9 +23,9 @@ * * @param sPath Location of directory to scan * @param hDir Pointer to a Directory struct to fill in - * @returns 1 on success 0 on failure + * @returns true on success false on failure */ -unsigned Directory_Open(const char *sPath, Directory *hDirectory) +bool Directory_Open(const char *sPath, Directory *hDirectory) { assert(sPath); assert(*sPath); @@ -34,9 +34,9 @@ hDirectory->hDir = opendir(sPath); if(NULL == hDirectory->hDir) { - return 0; + return false; } else { - return 1; + return true; } } @@ -81,9 +81,9 @@ * * @param sPath Path to file to check * @param phFileInfo pointer to FileInfo struct to fill in - * @returns 0 on failure 1 on success + * @returns false on failure true on success */ -unsigned char File_GetInfo(const char *sPath, FileInfo *phFileInfo) +bool File_GetInfo(const char *sPath, FileInfo *phFileInfo) { struct stat hEntryInfo; @@ -93,25 +93,25 @@ if (stat(sPath, &hEntryInfo) != 0) { fprintf(stderr, "Warning: could not stat() entry \'%s\': %s\n", sPath, strerror(errno)); - return 0; + return false; } /* Initialise components */ - phFileInfo->bIsRegularFile = 0; - phFileInfo->bIsDirectory = 0; + phFileInfo->bIsRegularFile = false; + phFileInfo->bIsDirectory = false; if (S_ISREG(hEntryInfo.st_mode)) { - phFileInfo->bIsRegularFile = 1; + phFileInfo->bIsRegularFile = true; } if (S_ISDIR(hEntryInfo.st_mode)) { - phFileInfo->bIsDirectory = 1; + phFileInfo->bIsDirectory = true; } /* Fill in Size */ phFileInfo->ulFilesize = hEntryInfo.st_size; /* Success! */ - return 1; + return true; } Index: platform.h =================================================================== RCS file: /cvsroot/arcem/arcem/X/platform.h,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- platform.h 21 Dec 2004 22:08:09 -0000 1.1 +++ platform.h 12 May 2012 17:34:51 -0000 1.2 @@ -5,8 +5,17 @@ #ifndef _PLATFORM_H_ #define _PLATFORM_H_ +/* An upper limit on how big to support monitor size, used for + allocating a scanline buffer and bounds checking. It's much + more than a VIDC1 can handle, and should be pushing the RPC/A7000 + VIDC too, if we ever get around to supporting that. */ +#define MaxVideoWidth 2048 +#define MaxVideoHeight 1536 -struct host_display { +/* The size of the border surrounding the video data. */ +#define VIDC_BORDER 10 + +struct plat_display { Window RootWindow,BackingWindow,MainPane,ControlPane,CursorPane; Display *disp; Screen *xScreen; @@ -25,16 +34,25 @@ Pixmap shape_mask; /* window shape */ int ShapeEnabled; /* Yep - we are using shapes */ char *ShapePixmapData; /* This is what we use to create the pixmap */ - unsigned long pixelMap[256]; /* Map from host memory contents to 'pixel' value for putpixel */ - unsigned long border_map; - unsigned long cursorPixelMap[4]; /* Map from host memory contents to 'pixel' value for putpixel in cursor*/ int red_shift,red_prec; int green_shift,green_prec; int blue_shift,blue_prec; + + int DoingMouseFollow; // } HostDisplay; }; -extern struct host_display HD; +extern struct plat_display PD; + +extern void Resize_Window(ARMul_State *state,int x,int y); + +extern unsigned int vidc_col_to_x_col(unsigned int col); + +extern void hostdisplay_change_focus(int focus); +extern void UpdateCursorPos(ARMul_State *state,int xscale,int xoffset,int yscale,int yoffset); + +extern const DisplayDev true_DisplayDev; +extern const DisplayDev pseudo_DisplayDev; #endif /* _PLATFORM_H_ */ Index: DispKbd.c =================================================================== RCS file: /cvsroot/arcem/arcem/X/DispKbd.c,v retrieving revision 1.78 retrieving revision 1.79 diff -u -d -r1.78 -r1.79 --- DispKbd.c 25 Sep 2009 10:30:42 -0000 1.78 +++ DispKbd.c 12 May 2012 17:34:51 -0000 1.79 @@ -1,21 +1,11 @@ -/* (c) David Alan Gilbert 1995-1999 - see Readme file for copying info */ +/* (c) David Alan Gilbert 1995-1999 - see Readme file for copying info + Hacked about with for new display driver interface by Jeffrey Lee, 2011 */ /* Display and keyboard interface for the Arc emulator */ -/* Now does TrueColor and PseudoColor X modes; but doesnt handle palette - changes properly in TrueColor - in particular it doesn't force a redraw if - the palette is changed which it really needs to */ - -#define KEYREENABLEDELAY 1000 /*#define DEBUG_VIDCREGS */ [...1362 lines suppressed...] + PD.CursorImageData, 32, y, 32, 0); - insist(!!HD.CursorImage, "creating host cursor image"); + insist(!!PD.CursorImage, "creating host cursor image"); - HD.ShapePixmapData = ecalloc(32 * y, "host cursor shape mask"); + PD.ShapePixmapData = ecalloc(32 * y, "host cursor shape mask"); } /* ------------------------------------------------------------------ */ @@ -1660,7 +955,7 @@ void *p; if ((p = malloc(n)) == NULL) { - fprintf(stderr, "arcem: malloc of %u bytes for %s failed.\n", + fprintf(stderr, "arcem: malloc of %zu bytes for %s failed.\n", n, use); exit(1); } Index: ControlPane.c =================================================================== RCS file: /cvsroot/arcem/arcem/X/ControlPane.c,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- ControlPane.c 23 Mar 2006 13:46:03 -0000 1.16 +++ ControlPane.c 12 May 2012 17:34:51 -0000 1.17 @@ -10,9 +10,10 @@ #include "../armdefs.h" #include "archio.h" #include "armarc.h" -#include "DispKbd.h" #include "ControlPane.h" +#include "arch/displaydev.h" #include "platform.h" +#include "arch/keyboard.h" #include <string.h> @@ -23,13 +24,11 @@ #define LEDWIDTH 15 #define LEDTOPS 90 -#define DC DISPLAYCONTROL - /*-----------------------------------------------------------------------------*/ static void TextAt(ARMul_State *state, const char *Text, int x, int y) { - XDrawImageString(HD.disp, HD.ControlPane, HD.ControlPaneGC, x, y, + XDrawImageString(PD.disp, PD.ControlPane, PD.ControlPaneGC, x, y, Text, strlen(Text)); } /* TextAt */ @@ -38,30 +37,30 @@ static void DoLED(const char *Text, int On, int ty, int lx) { - XSetBackground(HD.disp, HD.ControlPaneGC, HD.OffWhite.pixel); - XSetForeground(HD.disp, HD.ControlPaneGC, HD.Black.pixel); + XSetBackground(PD.disp, PD.ControlPaneGC, PD.OffWhite.pixel); + XSetForeground(PD.disp, PD.ControlPaneGC, PD.Black.pixel); TextAt(NULL, Text, lx + LEDWIDTH + 2, ty); - XSetForeground(HD.disp, HD.ControlPaneGC, HD.Black.pixel); - XSetFillStyle(HD.disp, HD.ControlPaneGC, FillSolid); + XSetForeground(PD.disp, PD.ControlPaneGC, PD.Black.pixel); + XSetFillStyle(PD.disp, PD.ControlPaneGC, FillSolid); - XDrawArc(HD.disp, HD.ControlPane, HD.ControlPaneGC, lx, ty-LEDHEIGHT, LEDWIDTH, LEDHEIGHT, + XDrawArc(PD.disp, PD.ControlPane, PD.ControlPaneGC, lx, ty-LEDHEIGHT, LEDWIDTH, LEDHEIGHT, 0, 360*64); - XSetForeground(HD.disp, HD.ControlPaneGC, (On?HD.Green:HD.GreyDark).pixel); - XFillArc(HD.disp, HD.ControlPane, HD.ControlPaneGC, lx+2, ty+6-(LEDHEIGHT+4), LEDWIDTH-4, (LEDHEIGHT-4), + XSetForeground(PD.disp, PD.ControlPaneGC, (On?PD.Green:PD.GreyDark).pixel); + XFillArc(PD.disp, PD.ControlPane, PD.ControlPaneGC, lx+2, ty+6-(LEDHEIGHT+4), LEDWIDTH-4, (LEDHEIGHT-4), 0, 360*64); } /* DoLED */ /*----------------------------------------------------------------------------*/ -static void draw_keyboard_leds(unsigned int leds) +static void draw_keyboard_leds(uint8_t leds) { - DoLED("Caps Lock", leds & 1, LEDTOPS, 0); - DoLED("Num Lock", leds & 2, LEDTOPS, 90); - DoLED("Scroll Lock", leds & 4, LEDTOPS, 180); + DoLED("Caps Lock", leds & KBD_LED_CAPSLOCK, LEDTOPS, 0); + DoLED("Num Lock", leds & KBD_LED_NUMLOCK, LEDTOPS, 90); + DoLED("Scroll Lock", leds & KBD_LED_SCROLLLOCK, LEDTOPS, 180); } @@ -113,7 +112,7 @@ XCharStruct overall; int x; - XTextExtents(HD.ButtonFont, Text, strlen(Text), + XTextExtents(PD.ButtonFont, Text, strlen(Text), &dirreturn, &ascentret, &descentret, &overall); /* Move the text down so that its top is where the caller asked */ @@ -131,8 +130,8 @@ static void ControlPane_Redraw(ARMul_State *state, XExposeEvent *e) { int y; - XSetBackground(HD.disp, HD.ControlPaneGC, HD.OffWhite.pixel); - XSetForeground(HD.disp, HD.ControlPaneGC, HD.Black.pixel); + XSetBackground(PD.disp, PD.ControlPaneGC, PD.OffWhite.pixel); + XSetForeground(PD.disp, PD.ControlPaneGC, PD.Black.pixel); y = TextCenteredH(state, "Archimedes Emulation (c) 1995-1999 David Alan Gilbert", 0, 0, CTRLPANEWIDTH); @@ -140,7 +139,7 @@ y = TextCenteredH(state, "http://arcem.sf.net/", y, 0, CTRLPANEWIDTH); y+=2; - XDrawLine(HD.disp, HD.ControlPane, HD.ControlPaneGC, + XDrawLine(PD.disp, PD.ControlPane, PD.ControlPaneGC, 0, y, CTRLPANEWIDTH-1, y); y += 2; @@ -193,8 +192,8 @@ char *tmpptr; int drive; - HD.ControlPane = XCreateWindow(HD.disp, - HD.RootWindow, /* HD.BackingWindow, */ + PD.ControlPane = XCreateWindow(PD.disp, + PD.RootWindow, /* PD.BackingWindow, */ 0, 0, /* above main pane */ CTRLPANEWIDTH, CTRLPANEHEIGHT, 0, /* Border width */ @@ -210,27 +209,27 @@ exit(1); } - XSetWMName(HD.disp, HD.ControlPane, &name); + XSetWMName(PD.disp, PD.ControlPane, &name); XFree(name.value); - HD.ControlPaneGC = XCreateGC(HD.disp, HD.ControlPane, 0, NULL); - XCopyGC(HD.disp, DefaultGC(HD.disp, HD.ScreenNum), GCPlaneMask|GCSubwindowMode, - HD.ControlPaneGC); + PD.ControlPaneGC = XCreateGC(PD.disp, PD.ControlPane, 0, NULL); + XCopyGC(PD.disp, DefaultGC(PD.disp, PD.ScreenNum), GCPlaneMask|GCSubwindowMode, + PD.ControlPaneGC); - HD.ButtonFont = XLoadQueryFont(HD.disp, "fixed"); + PD.ButtonFont = XLoadQueryFont(PD.disp, "fixed"); - if (HD.ButtonFont == NULL) { + if (PD.ButtonFont == NULL) { fprintf(stderr, "Couldn't get font for buttons\n"); exit(1); } - XSetFont(HD.disp, HD.ControlPaneGC, HD.ButtonFont->fid); + XSetFont(PD.disp, PD.ControlPaneGC, PD.ButtonFont->fid); - XSetWindowBackground(HD.disp, HD.ControlPane, HD.OffWhite.pixel); + XSetWindowBackground(PD.disp, PD.ControlPane, PD.OffWhite.pixel); - XSelectInput(HD.disp, HD.ControlPane, KeyPressMask | ExposureMask); + XSelectInput(PD.disp, PD.ControlPane, KeyPressMask | ExposureMask); - XMapWindow(HD.disp, HD.ControlPane); + XMapWindow(PD.disp, PD.ControlPane); /* setup callbacks for each time various LEDs change */ KBD.leds_changed = draw_keyboard_leds; --- NEW FILE: true.c --- /* X/true.c (c) 2011 Jeffrey Lee <m...@phlamethrower.co.uk> Standard display device implementation for truecolour X11 displays */ #include <limits.h> #include <X11/X.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/keysym.h> #include <X11/extensions/shape.h> #if defined(sun) && defined(__SVR4) # include <X11/Sunkeysym.h> #endif #include "../armdefs.h" #include "armarc.h" #include "arch/keyboard.h" #include "archio.h" #include "../armemu.h" #include "arch/displaydev.h" #include "platform.h" typedef unsigned int SDD_HostColour; #define SDD_Name(x) true_##x static const int SDD_RowsAtOnce = 1; typedef struct { int x,y; /* Current image position */ } SDD_Row; #define SDD_DisplayDev true_DisplayDev static int UpdateMinX=INT_MAX,UpdateMaxX=-1; static int UpdateMinY=INT_MAX,UpdateMaxY=-1; static SDD_HostColour SDD_Name(Host_GetColour)(ARMul_State *state,unsigned int col) { return vidc_col_to_x_col(col); } static void SDD_Name(Host_ChangeMode)(ARMul_State *state,int width,int height,int hz); static inline SDD_Row SDD_Name(Host_BeginRow)(ARMul_State *state,int row,int offset) { SDD_Row dhrow; dhrow.x = offset; dhrow.y = row; return dhrow; } static inline void SDD_Name(Host_EndRow)(ARMul_State *state,SDD_Row *row) { /* nothing */ }; static inline void SDD_Name(Host_BeginUpdate)(ARMul_State *state,SDD_Row *row,unsigned int count) { UpdateMinX = MIN(UpdateMinX,row->x); UpdateMaxX = MAX(UpdateMaxX,row->x+count-1); UpdateMinY = MIN(UpdateMinY,row->y); UpdateMaxY = MAX(UpdateMaxY,row->y); } static inline void SDD_Name(Host_EndUpdate)(ARMul_State *state,SDD_Row *row) { /* nothing */ }; static inline void SDD_Name(Host_SkipPixels)(ARMul_State *state,SDD_Row *row,unsigned int count) { row->x += count; } static inline void SDD_Name(Host_WritePixel)(ARMul_State *state,SDD_Row *row,SDD_HostColour pix) { XPutPixel(PD.DisplayImage, row->x++, row->y, pix); } static inline void SDD_Name(Host_WritePixels)(ARMul_State *state,SDD_Row *row,SDD_HostColour pix,unsigned int count) { while(count--) { XPutPixel(PD.DisplayImage, row->x++, row->y, pix); } } static void SDD_Name(Host_PollDisplay)(ARMul_State *state); #include "../arch/stddisplaydev.c" static void SDD_Name(Host_ChangeMode)(ARMul_State *state,int width,int height,int hz) { if (width > MaxVideoWidth || height > MaxVideoHeight) { fprintf(stderr, "Resize_Window: new size (%d, %d) exceeds maximum (%d, %d)\n", width, height, MaxVideoWidth, MaxVideoHeight); exit(EXIT_FAILURE); } HD.XScale = 1; HD.YScale = 1; /* Try and detect rectangular pixel modes */ if((width >= height*2) && (height*2 <= MaxVideoHeight)) { HD.YScale = 2; height *= 2; } else if((height >= width) && (width*2 <= MaxVideoWidth)) { HD.XScale = 2; width *= 2; } HD.Width = MIN(MaxVideoWidth,width + (VIDC_BORDER * 2)); HD.Height = MIN(MaxVideoHeight,height + (VIDC_BORDER * 2)); Resize_Window(state,HD.Width,HD.Height); UpdateMinX=UpdateMinY=0; UpdateMaxX=HD.Width-1; UpdateMaxY=HD.Height-1; } /* Refresh the mouses image */ static void RefreshMouse(ARMul_State *state) { int x, y, height, offset; int memptr, TransBit; char *ImgPtr, *TransPtr; offset = 0; memptr = MEMC.Cinit * 16; height = (VIDC.Vert_CursorEnd - VIDC.Vert_CursorStart) + 1; ImgPtr = PD.CursorImageData; TransPtr = PD.ShapePixmapData; TransBit = 0; SDD_HostColour cursorPalette[3]; for(x=0;x<3;x++) { cursorPalette[x] = SDD_Name(Host_GetColour)(state,VIDC.CursorPalette[x]); } for(y=0; y<height; y++,memptr+=8,offset+=8,TransPtr+=4) { if (offset < 512*1024) { ARMword tmp[2]; tmp[0] = MEMC.PhysRam[memptr/4]; tmp[1] = MEMC.PhysRam[memptr/4+1]; for(x=0; x<32; x++,ImgPtr++,TransBit<<=1) { int idx = ((tmp[x / 16] >> ((x & 15) * 2)) & 3); XPutPixel(PD.CursorImage, x, y, cursorPalette[idx-1]); if ((x & 7) == 0) { TransPtr[x / 8] = 0xff; TransBit = 1; } TransPtr[x / 8] &= idx ? ~TransBit : 0xff; } /* x */ } else { return; } } /* y */ if (PD.ShapeEnabled) { int DisplayHeight = VIDC.Vert_DisplayEnd - VIDC.Vert_DisplayStart; if(DisplayHeight > 0) { PD.shape_mask = XCreatePixmapFromBitmapData(PD.disp, PD.CursorPane, PD.ShapePixmapData, 32, DisplayHeight, 0, 1, 1); /* Eek - a lot of this is copied from XEyes - unfortunatly the manual page for this call is somewhat lacking. To quote its bugs entry: 'This manual page needs a lot more work' */ XShapeCombineMask(PD.disp,PD.CursorPane,ShapeBounding,0,0,PD.shape_mask, ShapeSet); XFreePixmap(PD.disp,PD.shape_mask); } }; /* Shape enabled */ } /* RefreshMouse */ static void SDD_Name(Host_PollDisplay)(ARMul_State *state) { if(UpdateMaxY >= 0) { int startx = UpdateMinX; int starty = UpdateMinY; int endx = UpdateMaxX; int endy = UpdateMaxY; if(starty != endy) { startx = 0; endx = HD.Width-1; } XPutImage(PD.disp, PD.MainPane, PD.MainPaneGC, PD.DisplayImage, startx, starty, /* source pos. in image */ startx, starty, /* Position on window */ endx-startx+1, endy-starty+1); UpdateMinX = UpdateMinY = INT_MAX; UpdateMaxX = UpdateMaxY = -1; } RefreshMouse(state); UpdateCursorPos(state,HD.XScale,HD.XOffset,HD.YScale,HD.YOffset); XPutImage(PD.disp, PD.CursorPane, PD.MainPaneGC, PD.CursorImage, 0, 0, 0, 0, 32, ((VIDC.Vert_CursorEnd - VIDC.Vert_CursorStart) - 1)); } --- NEW FILE: pseudo.c --- /* X/pseudo.c (c) 2011 Jeffrey Lee <m...@phlamethrower.co.uk> Standard display device implementation for pseudocolour X11 displays TODO - This should probably be converted to use the palettised display device */ #include <limits.h> #include <X11/X.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/keysym.h> #include <X11/extensions/shape.h> #if defined(sun) && defined(__SVR4) # include <X11/Sunkeysym.h> #endif #include "../armdefs.h" #include "armarc.h" #include "arch/keyboard.h" #include "archio.h" #include "../armemu.h" #include "arch/displaydev.h" #include "platform.h" typedef char SDD_HostColour; #define SDD_Name(x) pseudo_##x static const int SDD_RowsAtOnce = 1; typedef SDD_HostColour *SDD_Row; #define SDD_DisplayDev pseudo_DisplayDev static int UpdateStart=INT_MAX,UpdateEnd=-1; static SDD_HostColour SDD_Name(Host_GetColour)(ARMul_State *state,unsigned int col) { /* We use a fixed palette which matches the standard 256 colour RISC OS one */ int tint = (col & 0x3) + ((col & 0x30)>>4) + ((col & 0x300)>>8) + 1; return (tint/3)+(col&0xc)+((col&0xc0)>>2)+((col&0xc00)>>4); } static void SDD_Name(Host_ChangeMode)(ARMul_State *state,int width,int height,int hz); static inline SDD_Row SDD_Name(Host_BeginRow)(ARMul_State *state,int row,int offset); static inline void SDD_Name(Host_EndRow)(ARMul_State *state,SDD_Row *row) { /* nothing */ }; static inline void SDD_Name(Host_BeginUpdate)(ARMul_State *state,SDD_Row *row,unsigned int count) { UpdateStart = MIN(UpdateStart,*row-PD.ImageData); UpdateEnd = MAX(UpdateEnd,*row-PD.ImageData+count-1); } static inline void SDD_Name(Host_EndUpdate)(ARMul_State *state,SDD_Row *row) { /* nothing */ }; static inline void SDD_Name(Host_SkipPixels)(ARMul_State *state,SDD_Row *row,unsigned int count) { (*row) += count; } static inline void SDD_Name(Host_WritePixel)(ARMul_State *state,SDD_Row *row,SDD_HostColour pix) { *(*row)++ = pix; } static inline void SDD_Name(Host_WritePixels)(ARMul_State *state,SDD_Row *row,SDD_HostColour pix,unsigned int count) { while(count--) *(*row)++ = pix; } static void SDD_Name(Host_PollDisplay)(ARMul_State *state); #include "../arch/stddisplaydev.c" static inline SDD_Row SDD_Name(Host_BeginRow)(ARMul_State *state,int row,int offset) { return PD.ImageData+row*HD.Width+offset; } static void SDD_Name(Host_ChangeMode)(ARMul_State *state,int width,int height,int hz) { if (width > MaxVideoWidth || height > MaxVideoHeight) { fprintf(stderr, "Resize_Window: new size (%d, %d) exceeds maximum (%d, %d)\n", width, height, MaxVideoWidth, MaxVideoHeight); exit(EXIT_FAILURE); } HD.XScale = 1; HD.YScale = 1; /* Try and detect rectangular pixel modes */ if((width >= height*2) && (height*2 <= MaxVideoHeight)) { HD.YScale = 2; height *= 2; } else if((height >= width) && (width*2 <= MaxVideoWidth)) { HD.XScale = 2; width *= 2; } HD.Width = MIN(MaxVideoWidth,width + (VIDC_BORDER * 2)); HD.Height = MIN(MaxVideoHeight,height + (VIDC_BORDER * 2)); Resize_Window(state,HD.Width,HD.Height); UpdateStart = 0; UpdateEnd = HD.Width*HD.Height-1; } /* Refresh the mouses image */ static void RefreshMouse(ARMul_State *state) { int x, y, height, offset; int memptr, TransBit; char *ImgPtr, *TransPtr; offset = 0; memptr = MEMC.Cinit * 16; height = (VIDC.Vert_CursorEnd - VIDC.Vert_CursorStart) + 1; ImgPtr = PD.CursorImageData; TransPtr = PD.ShapePixmapData; TransBit = 0; SDD_HostColour cursorPalette[3]; for(x=0;x<3;x++) { cursorPalette[x] = SDD_Name(Host_GetColour)(state,VIDC.CursorPalette[x]); } for(y=0; y<height; y++,memptr+=8,offset+=8,TransPtr+=4) { if (offset < 512*1024) { ARMword tmp[2]; tmp[0] = MEMC.PhysRam[memptr/4]; tmp[1] = MEMC.PhysRam[memptr/4+1]; for(x=0; x<32; x++,ImgPtr++,TransBit<<=1) { int idx = ((tmp[x / 16] >> ((x & 15) * 2)) & 3); *ImgPtr = cursorPalette[idx-1]; if ((x & 7) == 0) { TransPtr[x / 8] = 0xff; TransBit = 1; } TransPtr[x / 8] &= idx ? ~TransBit : 0xff; } /* x */ } else { return; } } /* y */ if (PD.ShapeEnabled) { int DisplayHeight = VIDC.Vert_DisplayEnd - VIDC.Vert_DisplayStart; if(DisplayHeight > 0) { PD.shape_mask = XCreatePixmapFromBitmapData(PD.disp, PD.CursorPane, PD.ShapePixmapData, 32, DisplayHeight, 0, 1, 1); /* Eek - a lot of this is copied from XEyes - unfortunatly the manual page for this call is somewhat lacking. To quote its bugs entry: 'This manual page needs a lot more work' */ XShapeCombineMask(PD.disp,PD.CursorPane,ShapeBounding,0,0,PD.shape_mask, ShapeSet); XFreePixmap(PD.disp,PD.shape_mask); } }; /* Shape enabled */ } /* RefreshMouse */ static void SDD_Name(Host_PollDisplay)(ARMul_State *state) { if(UpdateEnd >= 0) { /* Work out the rectangle that covers this region */ int startx = UpdateStart % HD.Width; int starty = UpdateStart / HD.Width; int endx = UpdateEnd % HD.Width; int endy = UpdateEnd / HD.Width; if(starty != endy) { startx = 0; endx = HD.Width-1; } XPutImage(PD.disp, PD.MainPane, PD.MainPaneGC, PD.DisplayImage, startx, starty, /* source pos. in image */ startx, starty, /* Position on window */ endx-startx+1, endy-starty+1); UpdateStart = INT_MAX; UpdateEnd = -1; } RefreshMouse(state); UpdateCursorPos(state,HD.XScale,HD.XOffset,HD.YScale,HD.YOffset); XPutImage(PD.disp, PD.CursorPane, PD.MainPaneGC, PD.CursorImage, 0, 0, 0, 0, 32, ((VIDC.Vert_CursorEnd - VIDC.Vert_CursorStart) - 1)); } ------------------------------------------------------------------------------ Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ -- arcem-cvs mailing list arcem-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/arcem-cvs