Index: uae/aclocal.m4 diff -u uae/aclocal.m4:1.1.1.1 uae/aclocal.m4:1.2 --- uae/aclocal.m4:1.1.1.1 Mon Jan 6 15:37:07 2003 +++ uae/aclocal.m4 Mon Jan 6 16:23:47 2003 @@ -646,3 +646,59 @@ MINGW32= test "$am_cv_mingw32" = yes && MINGW32=yes]) +dnl PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not) +dnl defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page +dnl also defines GSTUFF_PKG_ERRORS on error +AC_DEFUN(PKG_CHECK_MODULES, [ + succeeded=no + + if test -z "$PKG_CONFIG"; then + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) + fi + + if test "$PKG_CONFIG" = "no" ; then + echo "*** The pkg-config script could not be found. Make sure it is" + echo "*** in your path, or set the PKG_CONFIG environment variable" + echo "*** to the full path to pkg-config." + echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config." + else + PKG_CONFIG_MIN_VERSION=0.9.0 + if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then + AC_MSG_CHECKING(for $2) + + if $PKG_CONFIG --exists "$2" ; then + AC_MSG_RESULT(yes) + succeeded=yes + + AC_MSG_CHECKING($1_CFLAGS) + $1_CFLAGS=`$PKG_CONFIG --cflags "$2"` + AC_MSG_RESULT($$1_CFLAGS) + + AC_MSG_CHECKING($1_LIBS) + $1_LIBS=`$PKG_CONFIG --libs "$2"` + AC_MSG_RESULT($$1_LIBS) + else + $1_CFLAGS="" + $1_LIBS="" + ## If we have a custom action on failure, don't print errors, but + ## do set a variable so people can do so. + $1_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` + ifelse([$4], ,echo $$1_PKG_ERRORS,) + fi + + AC_SUBST($1_CFLAGS) + AC_SUBST($1_LIBS) + else + echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer." + echo "*** See http://www.freedesktop.org/software/pkgconfig" + fi + fi + + if test $succeeded = yes; then + ifelse([$3], , :, [$3]) + else + ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4]) + fi +]) + + Index: uae/configure.in diff -u uae/configure.in:1.1.1.1 uae/configure.in:1.2 --- uae/configure.in:1.1.1.1 Mon Jan 6 15:37:07 2003 +++ uae/configure.in Mon Jan 6 16:23:47 2003 @@ -21,6 +21,8 @@ AC_PATH_PROG(RCLPRG, rcl, not-found) AC_PATH_PROG(SDL_CONFIG, sdl-config, not-found) +PKG_CHECK_MODULES( DIRECTFB, directfb >= 0.9.0, HAVE_DIRECTFB=yes, HAVE_DIRECTFB=no ) + AC_AIX AC_ISC_POSIX @@ -146,7 +148,6 @@ SDL_LIBS=`$SDL_CONFIG --libs` fi - dnl Verify that the ncurses installation makes some sense. if [[ "x$HAVE_NCURSES_LIB" = "xyes" ]]; then @@ -230,9 +231,10 @@ AC_ARG_WITH(svgalib,[ --with-svgalib Use SVGAlib for graphics output],[WANT_SVGALIB=$withval],[]) AC_ARG_WITH(sdl,[ --with-sdl Use SDL library for low-level functions],[WANT_SDL=$withval],[]) AC_ARG_WITH(sdl-sound,[ --with-sdl-sound Use SDL library for sound],[WANT_SDLSND=$withval],[]) -AC_ARG_WITH(sdl-gfx,[ --with-sdl-gfx Use SDL library for graphics],[WANT_SDLGFX=$withval],[]) +AC_ARG_WITH(sdl-gfx,[ --with-sdl-gfx Use SDL library for graphics],[WANT_SDLGFX=$withval],[]) +AC_ARG_WITH(directfb,[ --with-directfb Use DirectFB library],[WANT_DIRECTFB=$withval],[]) AC_ARG_WITH(asciiart,[ --with-asciiart Use ncurses ascii art for graphics output],[WANT_ASCIIART=$withval],[]) -AC_ARG_ENABLE(dga,[ --enable-dga X11 version: Use the DGA extension],[WANT_DGA=$enableval],[]) +AC_ARG_ENABLE(dga, [ --enable-dga X11 version: Use the DGA extension],[WANT_DGA=$enableval],[]) AC_ARG_ENABLE(vidmode,[ --enable-vidmode X11 version: Use the XF86VidMode extension],[WANT_VIDMODE=$enableval],[]) AC_ARG_ENABLE(ui,[ --enable-ui Use a user interface if possible (default on)],[WANT_UI=$enableval],[]) AC_ARG_WITH(hostcc,[ --with-hostcc=x Use a x as compiler for the host system],[HOSTCC=$withval],[HOSTCC=$CC]) @@ -256,6 +258,18 @@ fi fi +if [[ "x$WANT_DIRECTFB" = "xyes" ]]; then + if [[ "x$HAVE_DIRECTFB" = "xno" ]]; then + echo "Could not find DirectFB, disabling support." + NR_ERRORS=`expr $NR_ERRORS + 1` + WANT_DIRECTFB=no + else + no_x=yes + LIBS="$LIBS $DIRECTFB_LIBS" + ADDITIONAL_CFLAGS="$ADDITIONAL_CFLAGS $DIRECTFB_CFLAGS -DUSE_DIRECTFB" + fi +fi + if [[ "x$WANT_DGA" = "xyes" ]]; then if [[ "x$WANT_SVGALIB" = "xyes" -o "x$WANT_ASCIIART" = "xyes" -o "x$WANT_SDLGFX" = "xyes" ]]; then echo "You can't enable DGA for SVGAlib, SDL and ncurses targets!" @@ -387,6 +401,12 @@ GFXOBJS="sdlgfx.o" # @@@ Kludge. This may get changed later. TARGETDEP=t-x11.h +else if [[ "x$WANT_DIRECTFB" = "xyes" ]]; then + AC_MSG_RESULT(DirectFB) + MATHLIB= + TARGET=directfb + GFXOBJS="dfbgfx.o" + TARGETDEP=t-directfb.h else if [[ "x$HAVE_DIRECTX" = "xyes" ]]; then AC_MSG_RESULT(Win32/DirectX) MATHLIB= @@ -477,6 +497,7 @@ fi fi fi +fi if [[ "x$HAVE_DIRECTX" = "xyes" ]]; then TARGETDEP=t-win32.h @@ -813,7 +834,8 @@ fi if [[ "x$TARGET" = "xx11" -o "x$TARGET" = "xsvgalib" -o "x$TARGET" = "xamigaos" \ - -o "x$TARGET" = "xbeos" -o "x$TARGET" = "xasciiart" -o "x$TARGET" = "xp_os" ]]; then + -o "x$TARGET" = "xbeos" -o "x$TARGET" = "xasciiart" -o "x$TARGET" = "xp_os" \ + -o "x$TARGET" = "xdirectfb" ]]; then dnl On Unix, BeOS and AmigaOS system, zfile is supposed to work. Dunno about others. CFLAGS="$CFLAGS -DUSE_ZFILE" fi @@ -977,11 +999,14 @@ if [[ "x$WANT_SDL" = "xyes" ]]; then OD_JOYSTICK=sdl-joystick.c +else if [[ "x$WANT_DIRECTFB" = "xyes" ]]; then + OD_JOYSTICK=dfb-joystick.c else if [[ "x$ac_cv_header_machine_joystick_h" = "xyes" ]]; then AC_TRY_COMPILE([#include ],[{ struct joystick a; }], OD_JOYSTICK=od-linux/joystick.c,) else OD_JOYSTICK=$OSDEP/joystick.c +fi fi fi Index: uae/src/Makefile.in diff -u uae/src/Makefile.in:1.1.1.1 uae/src/Makefile.in:1.2 --- uae/src/Makefile.in:1.1.1.1 Mon Jan 6 15:37:07 2003 +++ uae/src/Makefile.in Mon Jan 6 16:23:47 2003 @@ -46,6 +46,8 @@ x11: progs +directfb: progs + svgalib: progs win32: progs $(RESOBJS) Index: uae/src/dfb-joystick.c diff -u /dev/null uae/src/dfb-joystick.c:1.1 --- /dev/null Mon Jan 6 16:33:12 2003 +++ uae/src/dfb-joystick.c Mon Jan 6 16:20:26 2003 @@ -0,0 +1,177 @@ +/* + * UAE - The Un*x Amiga Emulator + * + * DirectFB joystick support + * + * Copyright (C) 2002 Ville Syrjala + */ + +#include + +#include "sysconfig.h" +#include "sysdeps.h" + +#include "config.h" +#include "options.h" +#include "memory.h" +#include "custom.h" +#include "joystick.h" + +int nr_joysticks; + +extern IDirectFB *dfb; +static IDirectFBInputDevice *joy0, *joy1; + +struct joy_range { + int minx, maxx, miny, maxy; +} range0, range1; + +void +read_joystick( int nr, unsigned int *dir, int *button ) +{ + int x_axis, y_axis; + int left = 0, right = 0, top = 0, bot = 0; + + IDirectFBInputDevice *joy = nr == 0 ? joy0 : joy1; + struct joy_range *r = nr == 0 ? &range0 : &range1; + + *dir = 0; + *button = 0; + + if ((nr == 0 && !joy0) || + (nr == 1 && !joy1) || + (nr > 1)) + return; + + joy->GetXY( joy, &x_axis, &y_axis ); + + if (x_axis < r->minx) r->minx = x_axis; + if (y_axis < r->miny) r->miny = y_axis; + if (x_axis > r->maxx) r->maxx = x_axis; + if (y_axis > r->maxy) r->maxy = y_axis; + + if (x_axis < (r->minx + (r->maxx - r->minx) / 3)) + left = 1; + else if (x_axis > (r->minx + 2 * (r->maxx - r->minx) / 3)) + right = 1; + + if (y_axis < (r->miny + (r->maxy - r->miny) / 3)) + top = 1; + else if (y_axis > (r->miny + 2 * (r->maxy - r->miny) / 3)) + bot = 1; + + if (left) + top = !top; + if (right) + bot = !bot; + *dir = bot | (right << 1) | (top << 8) | (left << 9); + + joy->GetButtons( joy, (DFBInputDeviceButtonMask *) button ); +} + +struct joy_enum { + DFBInputDeviceID id0, id1; + int wanted0, wanted1; + int found0, found1; +}; + +static DFBEnumerationResult +find_joysticks( DFBInputDeviceID id, DFBInputDeviceDescription desc, void *data ) +{ + struct joy_enum *j = (struct joy_enum *) data; + + if ((j->found0 || !j->wanted0) && + (j->found1 || !j->wanted1)) + return DFENUM_CANCEL; + + if (!(desc.type & DIDTF_JOYSTICK)) + return DFENUM_OK; + + if (id == j->id0) { + if (j->wanted0 && !j->found0) + j->found0 = 1; + } else if (id == j->id1) { + if (j->wanted1 && !j->found1) + j->found1 = 1; + } else if (j->wanted0 && !j->found0 && !j->id0) { + j->id0 = id; + j->found0 = 1; + } else if (j->wanted1 && !j->found1 && !j->id1) { + j->id1 = id; + j->found1 = 1; + } + + return DFENUM_OK; +} + +void +init_joystick( void ) +{ + DFBResult ret; + + struct joy_enum j = { + 0, 0, 0, 0, 0, 0 + }; + + nr_joysticks = 0; + + joy0 = NULL; + joy1 = NULL; + + /* Check if joysticks are wanted */ + if (currprefs.jport0 == 0 || currprefs.jport1 == 0) + j.wanted0 = 1; + if (currprefs.jport0 == 1 || currprefs.jport1 == 1) + j.wanted1 = 1; + + if (!j.wanted0 && !j.wanted1) + return; + + /* Check if spcific IDs are requested */ + if (currprefs.directfb_joy0_id > 0) + j.id0 = currprefs.directfb_joy0_id; + if (currprefs.directfb_joy1_id > 0) + j.id1 = currprefs.directfb_joy1_id; + + dfb->EnumInputDevices( dfb, find_joysticks, &j ); + + if (j.wanted0 && !j.found0) + fprintf( stderr, "Can't find a joystick for jport0\n" ); + if (j.wanted1 && !j.found1) + fprintf( stderr, "Can't find a joystick for jport1\n" ); + + if (j.found0) { + if (dfb->GetInputDevice( dfb, j.id0, &joy0 ) != DFB_OK) { + fprintf( stderr, "dfb->GetInputDevice() failed: %s\n", + DirectFBErrorString( ret ) ); + } else { + nr_joysticks++; + } + } + if (j.found1) { + if (dfb->GetInputDevice( dfb, j.id1, &joy1 ) != DFB_OK) { + fprintf( stderr, "dfb->GetInputDevice() failed: %s\n", + DirectFBErrorString( ret ) ); + } else { + nr_joysticks++; + } + } + + range0.minx = INT_MAX; + range0.maxx = INT_MIN; + range0.miny = INT_MAX; + range0.maxy = INT_MIN; + range1.minx = INT_MAX; + range1.maxx = INT_MIN; + range1.miny = INT_MAX; + range1.maxy = INT_MIN; +} + +void +close_joystick( void ) +{ + if (joy0) + joy0->Release( joy0 ); + if (joy1) + joy1->Release( joy1 ); +} Index: uae/src/dfbgfx.c diff -u /dev/null uae/src/dfbgfx.c:1.1 --- /dev/null Mon Jan 6 16:33:12 2003 +++ uae/src/dfbgfx.c Mon Jan 6 16:20:23 2003 @@ -0,0 +1,1173 @@ +/* + * UAE - The Un*x Amiga Emulator + * + * DirectFB graphics & input support + * + * Copyright (C) 2002 Ville Syrjala + */ + +#include +#include + +#include + +#include "sysconfig.h" +#include "sysdeps.h" +#include "config.h" +#include "options.h" +#include "threaddep/thread.h" +#include "uae.h" +#include "memory.h" +#include "xwin.h" +#include "custom.h" +#include "drawing.h" +#include "newcpu.h" +#include "keyboard.h" +#include "keybuf.h" +#include "gui.h" +#include "debug.h" +#include "picasso96.h" + +/* Don't make static. Used in dfb-joystick.c */ +IDirectFB *dfb; + +static IDirectFBDisplayLayer *layer; +static IDirectFBWindow *window; +static IDirectFBSurface *surface; +static IDirectFBInputDevice *keyboard; +static IDirectFBInputDevice *mouse; +static IDirectFBEventBuffer *buffer; +static IDirectFBPalette *palette; + +static int screen_is_picasso; +static int grabbed; +static int fullscreen; +static int screen_height, screen_width, screen_pixfmt; + +static int picasso_invalid_lines; +static int picasso_invalid_start; +static int picasso_invalid_end; + +static int keystate[256]; + +static int red_bits, green_bits, blue_bits; +static int red_shift, green_shift, blue_shift; + +static int ncolors; + +#ifndef DSPF_ARGB1555 +#define DSPF_ARGB1555 DSPF_RGB15 +#endif + +/* Functions to handle special keys */ +static void +handle_modeswitch( void ) +{ + changed_prefs.gfx_afullscreen = changed_prefs.gfx_pfullscreen = !fullscreen; +} + +static void +handle_mousegrab( void ) +{ + if (fullscreen) + return; + + if (grabbed) { + window->UngrabKeyboard( window ); + window->UngrabPointer( window ); + + /* Show cursor */ + layer->SetCursorOpacity( layer, 0xff ); + + grabbed = 0; + } else { + window->GrabKeyboard( window ); + window->GrabPointer( window ); + + /* Hide cursor */ + layer->SetCursorOpacity( layer, 0 ); + + grabbed = 1; + } +} + +static void +handle_inhibit( void ) +{ + toggle_inhibit_frame( IHF_SCROLLLOCK ); +} + +static void +handle_interpol( void ) +{ + currprefs.sound_interpol = (currprefs.sound_interpol + 1) % 3; +} + +static void +framerate_up( void ) +{ + if (currprefs.gfx_framerate < 20) + changed_prefs.gfx_framerate = currprefs.gfx_framerate + 1; +} + +static void +framerate_down( void ) +{ + if (currprefs.gfx_framerate > 1) + changed_prefs.gfx_framerate = currprefs.gfx_framerate - 1; +} + +struct uae_hotkeys { + DFBInputDeviceKeyIdentifier ids[4]; + void (*handler)(void); + int retval; + int mask; +}; + +static struct uae_hotkeys hotkeys[] = { +{{ DIKI_F12, DIKI_S, 0 }, handle_modeswitch, -1, 0 }, +{{ DIKI_F12, DIKI_Q, 0 }, uae_quit, -1, 0 }, +{{ DIKI_F12, DIKI_M, 0 }, togglemouse, -1, 0 }, +{{ DIKI_F12, DIKI_G, 0 }, handle_mousegrab, -1, 0 }, +{{ DIKI_F12, DIKI_I, 0 }, handle_inhibit, -1, 0 }, +{{ DIKI_F12, DIKI_P, 0 }, handle_interpol, -1, 0 }, +{{ DIKI_F12, DIKI_KP_PLUS, 0 }, framerate_up, -1, 0 }, +{{ DIKI_F12, DIKI_KP_MINUS, 0 }, framerate_down, -1, 0 }, +{{ DIKI_SCROLL_LOCK, 0 }, handle_inhibit, -1, 0 }, +{{ 0 }, NULL, -1, 0 } +}; + + +static DFBSurfacePixelFormat +colormode_to_pixfmt( int colormode ) +{ + switch (colormode) { + case 0: + case 3: + case 4: + return DSPF_LUT8; + case 1: + return DSPF_ARGB1555; + case 2: + return DSPF_RGB16; + default: + return DSPF_RGB32; + } +} + +static DFBSurfacePixelFormat +rgbfmt_to_pixfmt( int rgbfmt ) +{ + switch (rgbfmt) { + case RGBFB_CLUT: + return DSPF_LUT8; + case RGBFB_R5G5B5PC: + return DSPF_ARGB1555; + case RGBFB_R5G6B5PC: + return DSPF_RGB16; + case RGBFB_B8G8R8: + return DSPF_RGB24; + case RGBFB_B8G8R8A8: + return DSPF_ARGB; + default: + return DSPF_RGB16; + } +} + +/* Set colors in a DirectFB palette */ +static int +alloc_color( int r, int g, int b, xcolnr *cnp ) +{ + DFBColor color = { + 0xff, + r << 4, + g << 4, + b << 4 + }; + + palette->SetEntries( palette, &color, 1, ncolors ); + *cnp = ncolors; + + ncolors++; + + return 1; +} + +static int +dfb_gfx_init( void ) +{ + DFBResult ret; + DFBDisplayLayerID layer_id = DLID_PRIMARY; + DFBSurfacePixelFormat pixelformat; + int width, height, pitch, i, j; + DFBSurfaceDescription dsc; + void *data; + + window = NULL; + surface = NULL; + palette = NULL; + keyboard = NULL; + mouse = NULL; + buffer = NULL; + layer = NULL; + + fullscreen = screen_is_picasso ? currprefs.gfx_pfullscreen : currprefs.gfx_afullscreen; + + width = screen_width; + height = screen_height; + pixelformat = screen_pixfmt; + + if (currprefs.directfb_layer_id > 0) + layer_id = currprefs.directfb_layer_id; + + if ((ret = dfb->GetDisplayLayer( dfb, layer_id, &layer )) != DFB_OK) { + fprintf( stderr, "dfb->GetDisplayLayer() failed: %s\n", + DirectFBErrorString( ret ) ); + return 0; + } + + if (fullscreen) { + DFBDisplayLayerConfig dlc; + DFBDisplayLayerConfigFlags failed; + + /* Exclusive access to the layer */ + if ((ret = layer->SetCooperativeLevel( layer, DLSCL_EXCLUSIVE )) != DFB_OK) { + fprintf( stderr, "layer->SetCooperativeLevel() failed: %s\n", + DirectFBErrorString( ret ) ); + return 0; + } + + /* Set layer config */ + dlc.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE; + dlc.width = width; + dlc.height = height; + dlc.pixelformat = pixelformat; + dlc.buffermode = DLBM_FRONTONLY; + + if (layer->TestConfiguration( layer, &dlc, &failed ) != DFB_OK) { + /* Remove offending flags */ + if (failed & DLCONF_WIDTH) + dlc.flags &= ~DLCONF_WIDTH; + if (failed & DLCONF_HEIGHT) + dlc.flags &= ~DLCONF_HEIGHT; + if (failed & DLCONF_PIXELFORMAT) + dlc.flags &= ~DLCONF_PIXELFORMAT; + if (failed & DLCONF_BUFFERMODE) + dlc.flags &= ~DLCONF_BUFFERMODE; + + /* Try again */ + if ((ret = layer->TestConfiguration( layer, &dlc, &failed )) != DFB_OK) { + fprintf( stderr, "layer->TestComfiguration() failed: %s\n", + DirectFBErrorString( ret ) ); + return 0; + } + } + layer->SetConfiguration( layer, &dlc ); + + if ((ret = layer->GetSurface( layer, &surface )) != DFB_OK) { + fprintf( stderr, "layer->GetSurface() failed: %s\n", + DirectFBErrorString( ret ) ); + return 0; + } + } else { + DFBWindowDescription wd; + + /* Shared access to the layer */ + if ((ret = layer->SetCooperativeLevel( layer, DLSCL_SHARED )) != DFB_OK) { + fprintf( stderr, "layer->SetCooperativeLevel() failed: %s\n", + DirectFBErrorString( ret ) ); + return 0; + } + + /* Create the window */ + wd.flags = DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_PIXELFORMAT; + wd.width = width; + wd.height = height; + wd.pixelformat = pixelformat; + + if (layer->CreateWindow( layer, &wd, &window ) != DFB_OK) { + fprintf( stderr, "layer->CreateWindow() failed\n" ); + return 0; + } + + if ((ret = window->GetSurface( window, &surface )) != DFB_OK) { + fprintf( stderr, "window->GetSurface() failed: %s\n", + DirectFBErrorString( ret ) ); + return 0; + } + } + + /* Clear the surface */ + surface->Clear( surface, 0, 0, 0, 0xff ); + if (!fullscreen) { + surface->Flip( surface, NULL, 0 ); + window->SetOpacity( window, 0xff ); + } + + /* Get the actual surface info from DirectFB */ + surface->GetSize( surface, &width, &height ); + surface->GetPixelFormat( surface, &pixelformat ); + + /* Handle color allocation */ + if (DFB_PIXELFORMAT_IS_INDEXED( pixelformat )) { + if ((ret = surface->GetPalette( surface, &palette )) != DFB_OK) { + fprintf( stderr, "surface->GetPalette() failed: %s\n", + DirectFBErrorString( ret ) ); + return 0; + } + if (screen_is_picasso) { + DX_SetPalette( 0, 256 ); + } else { + ncolors = 0; + alloc_colors256( alloc_color ); + } + } else { + if (screen_is_picasso) + DX_SetPalette( 0, 256 ); + else { + switch (pixelformat) { + case DSPF_ARGB1555: + red_bits = 5; + green_bits = 5; + blue_bits = 5; + red_shift = 10; + green_shift = 5; + blue_shift = 0; + break; + case DSPF_RGB16: + red_bits = 5; + green_bits = 6; + blue_bits = 5; + red_shift = 11; + green_shift = 5; + blue_shift = 0; + break; + case DSPF_RGB24: + case DSPF_RGB32: + case DSPF_ARGB: + red_bits = 8; + green_bits = 8; + blue_bits = 8; + red_shift = 16; + green_shift = 8; + blue_shift = 0; + break; + default: + fprintf( stderr, "Unknown pixelformat\n" ); + return 0; + } + alloc_colors64k( red_bits, green_bits, blue_bits, + red_shift, green_shift, blue_shift ); + } + } + + /* Fill vidinfo structs */ + surface->Lock( surface, DSLF_READ | DSLF_WRITE, &data, &pitch ); + surface->Unlock( surface ); + if (!screen_is_picasso) { + gfxvidinfo.bufmem = data; + gfxvidinfo.linemem = NULL; + gfxvidinfo.emergmem = (char *) malloc( pitch ); + gfxvidinfo.pixbytes = DFB_BYTES_PER_PIXEL( pixelformat ); + gfxvidinfo.rowbytes = pitch; + gfxvidinfo.maxblocklines = height; + gfxvidinfo.width = width; + gfxvidinfo.height = height; + + switch (DFB_BYTES_PER_PIXEL( pixelformat )) { + case 1: + for (i = 0; i < 4096; i++) + xcolors[i] *= 0x01010101; + gfxvidinfo.can_double = 1; + break; + case 2: + for (i = 0; i < 4096; i++) + xcolors[i] *= 0x00010001; + gfxvidinfo.can_double = 1; + break; + default: + gfxvidinfo.can_double = 0; + break; + } + } else { + picasso_vidinfo.pixbytes = DFB_BYTES_PER_PIXEL( pixelformat ); + picasso_vidinfo.rowbytes = pitch; + picasso_vidinfo.extra_mem = 1; + picasso_vidinfo.width = width; + picasso_vidinfo.height = height; + picasso_vidinfo.depth = DFB_BYTES_PER_PIXEL( pixelformat ); + + switch (pixelformat) { + case DSPF_LUT8: + picasso_vidinfo.rgbformat = RGBFB_CLUT; + break; + case DSPF_ARGB1555: + picasso_vidinfo.rgbformat = RGBFB_R5G5B5PC; + break; + case DSPF_RGB16: + picasso_vidinfo.rgbformat = RGBFB_R5G6B5PC; + break; + case DSPF_RGB24: + picasso_vidinfo.rgbformat = RGBFB_B8G8R8; + break; + case DSPF_ARGB: + case DSPF_RGB32: + picasso_vidinfo.rgbformat = RGBFB_B8G8R8A8; + break; + } + } + + /* Get input devices */ + if (fullscreen) { + if ((ret = dfb->GetInputDevice( dfb, DIDID_KEYBOARD, &keyboard )) != DFB_OK) { + fprintf( stderr, "dfb->GetInputDevice() failed: %s\n", + DirectFBErrorString( ret ) ); + return 0; + } + if ((ret = dfb->GetInputDevice( dfb, DIDID_MOUSE, &mouse )) != DFB_OK) { + fprintf( stderr, "dfb->GetInputDevice() failed: %s\n", + DirectFBErrorString( ret ) ); + return 0; + } + keyboard->CreateEventBuffer( keyboard, &buffer ); + mouse->AttachEventBuffer( mouse, buffer ); + } else { + window->CreateEventBuffer( window, &buffer ); + } + + /* Reset values */ + lastmx = lastmy = 0; + newmousecounters = 0; + picasso_invalid_lines = 0; + + for (i = 0; hotkeys[i].ids[0] != 0; i++) { + hotkeys[i].mask = 0; + for (j = 0; hotkeys[i].ids[j] != 0; j++) + hotkeys[i].mask |= 1 << j; + } + + return 1; +} + +int +graphics_init (void) +{ + int i; + + if (currprefs.color_mode > 5) + currprefs.color_mode = 0; + + fixup_prefs_dimensions( &currprefs ); + + screen_width = currprefs.gfx_width; + screen_height = currprefs.gfx_height; + screen_pixfmt = colormode_to_pixfmt( currprefs.color_mode ); + + for (i = 0; i < 3; i++) + buttonstate[i] = 0; + for (i = 0; i < 256; i++) + keystate[i] = 0; + + screen_is_picasso = 0; + grabbed = 0; + + return dfb_gfx_init(); +} + +int +graphics_setup( void ) +{ + if (DirectFBCreate( &dfb ) != DFB_OK) + return 0; + + return 1; +} + +/* Shutdown DirectFB graphics & input */ +static void +dfb_gfx_shutdown( void ) +{ + if (palette) + palette->Release( palette ); + if (surface) + surface->Release( surface ); + if (buffer) + buffer->Release( buffer ); + if (keyboard) + keyboard->Release( keyboard ); + if (mouse) + mouse->Release( mouse ); + if (window) + window->Release( window ); + if (layer) + layer->Release( layer ); + + palette = NULL; + surface = NULL; + buffer = NULL; + keyboard = NULL; + mouse = NULL; + window = NULL; + layer = NULL; + + if (gfxvidinfo.emergmem) + free( gfxvidinfo.emergmem ); + + gfxvidinfo.emergmem = NULL; +} + +void +graphics_leave( void ) +{ + dfb_gfx_shutdown(); + + dfb->Release( dfb ); +} + +void +setup_brkhandler( void ) +{ +} + +void +flush_line( int lineno ) +{ + /* no-op */ +} + +void +flush_block( int ystart, int yend ) +{ + /* Nothing to do if we're drawing to the layer surface */ + + if (!fullscreen) { + DFBRegion region = { + 0, ystart, + gfxvidinfo.width, yend + }; + surface->Unlock( surface ); + surface->Flip( surface, ®ion, 0 ); + } +} + +void +flush_screen( int a, int b ) +{ + /* no-op */ +} + +int lockscr( void ) +{ + int pitch; + void *data; + + if (surface->Lock( surface, DSLF_READ | DSLF_WRITE, + &data, &pitch ) != DFB_OK) + return 0; + else + return 1; +} + +void unlockscr( void ) +{ + surface->Unlock( surface ); +} + +int check_prefs_changed_gfx( void ) +{ + if (changed_prefs.gfx_width != currprefs.gfx_width || + changed_prefs.gfx_height != currprefs.gfx_height) + fixup_prefs_dimensions(&changed_prefs); + + if (changed_prefs.gfx_width == currprefs.gfx_width && + changed_prefs.gfx_height == currprefs.gfx_height && + changed_prefs.gfx_lores == currprefs.gfx_lores && + changed_prefs.gfx_linedbl == currprefs.gfx_linedbl && + changed_prefs.gfx_correct_aspect == currprefs.gfx_correct_aspect && + changed_prefs.gfx_xcenter == currprefs.gfx_xcenter && + changed_prefs.gfx_ycenter == currprefs.gfx_ycenter && + changed_prefs.gfx_afullscreen == currprefs.gfx_afullscreen && + changed_prefs.gfx_pfullscreen == currprefs.gfx_pfullscreen) + return 0; + + dfb_gfx_shutdown(); + + currprefs.gfx_width = changed_prefs.gfx_width; + currprefs.gfx_height = changed_prefs.gfx_height; + currprefs.gfx_lores = changed_prefs.gfx_lores; + currprefs.gfx_linedbl = changed_prefs.gfx_linedbl; + currprefs.gfx_correct_aspect = changed_prefs.gfx_correct_aspect; + currprefs.gfx_xcenter = changed_prefs.gfx_xcenter; + currprefs.gfx_ycenter = changed_prefs.gfx_ycenter; + currprefs.gfx_afullscreen = changed_prefs.gfx_afullscreen; + currprefs.gfx_pfullscreen = changed_prefs.gfx_pfullscreen; + + dfb_gfx_init(); + + gui_update_gfx(); + + notice_screen_contents_lost(); + init_row_map(); + if (screen_is_picasso) + picasso_enablescreen( 1 ); + + return 0; +} + +int +debuggable( void ) +{ + return 1; +} + +int +needmousehack( void ) +{ + return 1; +} + +void +LED( int on ) +{ +} + +uae_u8 *gfx_lock_picasso( void ) +{ + int pitch; + void *data; + + if (surface->Lock( surface, DSLF_READ | DSLF_WRITE, + &data, &pitch ) != DFB_OK) + return NULL; + else + return data; +} + +void gfx_unlock_picasso( void ) +{ + surface->Unlock( surface ); + + /* Update screen contents for picasso96 window */ + if (!fullscreen && picasso_invalid_lines) { + DFBRegion region = { + 0, picasso_invalid_start, + picasso_vidinfo.width, picasso_invalid_end + }; + + surface->Flip( surface, ®ion, 0 ); + picasso_invalid_lines = 0; + } +} + +void +gfx_set_picasso_baseaddr( uaecptr a ) +{ +} + +void +gfx_set_picasso_state( int on ) +{ + if (screen_is_picasso == on) + return; + + dfb_gfx_shutdown(); + + screen_is_picasso = on; + + if (on) { + screen_pixfmt = rgbfmt_to_pixfmt( picasso_vidinfo.selected_rgbformat ); + screen_width = picasso_vidinfo.width; + screen_height = picasso_vidinfo.height; + } else { + screen_pixfmt = colormode_to_pixfmt( currprefs.color_mode ); + screen_width = gfxvidinfo.width; + screen_height = gfxvidinfo.height; + } + + dfb_gfx_init(); +} + +void +gfx_set_picasso_modeinfo( int w, int h, int depth, int rgbfmt ) +{ + depth >>= 3; + if ((picasso_vidinfo.width == w ) && + (picasso_vidinfo.height == h ) && + (picasso_vidinfo.depth == depth) && + (picasso_vidinfo.selected_rgbformat == (unsigned int) rgbfmt)) + return; + + picasso_vidinfo.selected_rgbformat = rgbfmt; + picasso_vidinfo.width = w; + picasso_vidinfo.height = h; + + if (screen_is_picasso) { + dfb_gfx_shutdown(); + + screen_pixfmt = rgbfmt_to_pixfmt( rgbfmt ); + screen_width = w; + screen_height = h; + + dfb_gfx_init(); + } +} + +struct dfb_fill_enum +{ + int count; + uae_u16 format; +}; + +static DFBEnumerationResult +dfb_fill_resolutions( unsigned int width, + unsigned int height, + unsigned int bpp, + void *data ) +{ + struct dfb_fill_enum *f = (struct dfb_fill_enum *) data; + + DisplayModes[f->count].res.width = width; + DisplayModes[f->count].res.height = height; + DisplayModes[f->count].refresh = 75; + DisplayModes[f->count].depth = (bpp + 1) / 8; + + f->format |= bpp == 8 ? RGBFF_CLUT : + bpp == 15 ? RGBFF_R5G5B5PC : + bpp == 16 ? RGBFF_R5G6B5PC : + bpp == 24 ? RGBFF_B8G8R8 : + bpp == 32 ? RGBFF_B8G8R8A8 : + RGBFF_NONE; + f->count++; + + if (f->count >= MAX_PICASSO_MODES) + return DFENUM_CANCEL; + + return DFENUM_OK; +} + +int +DX_FillResolutions( uae_u16 *pixel_format ) +{ + struct dfb_fill_enum f = { 0, 0 }; + + dfb->EnumVideoModes( dfb, dfb_fill_resolutions, &f ); + + *pixel_format = f.format; + + return f.count; +} + +void +DX_SetPalette( int start, int count ) +{ + if (!screen_is_picasso || picasso96_state.RGBFormat != RGBFB_CLUT) + return; + + if (picasso_vidinfo.pixbytes != 1) { + /* This is the case when we're emulating a 256 color display. */ + while (count-- > 0) { + int r = picasso96_state.CLUT[start].Red; + int g = picasso96_state.CLUT[start].Green; + int b = picasso96_state.CLUT[start].Blue; + picasso_vidinfo.clut[start++] = + (doMask256(r, red_bits, red_shift) | + doMask256(g, green_bits, green_shift) | + doMask256(b, blue_bits, blue_shift)); + } + return; + } + + /* Set our DirectFB palette here */ + while (count--) { + DFBColor color = { + 0xff, + picasso96_state.CLUT[start].Red, + picasso96_state.CLUT[start].Green, + picasso96_state.CLUT[start].Blue + }; + + palette->SetEntries( palette, + &color, + 1, + start++ ); + } +} + +void +DX_Invalidate( int first, int last ) +{ + picasso_invalid_start = first; + picasso_invalid_end = last; + picasso_invalid_lines = 1; +} + +int +DX_BitsPerCannon( void ) +{ + return 8; +} + +static int +kc_decode( DFBInputDeviceKeyIdentifier id ) +{ + switch (id) { + case DIKI_B: return AK_B; + case DIKI_C: return AK_C; + case DIKI_D: return AK_D; + case DIKI_E: return AK_E; + case DIKI_F: return AK_F; + case DIKI_G: return AK_G; + case DIKI_H: return AK_H; + case DIKI_I: return AK_I; + case DIKI_J: return AK_J; + case DIKI_K: return AK_K; + case DIKI_L: return AK_L; + case DIKI_N: return AK_N; + case DIKI_O: return AK_O; + case DIKI_P: return AK_P; + case DIKI_R: return AK_R; + case DIKI_S: return AK_S; + case DIKI_T: return AK_T; + case DIKI_U: return AK_U; + case DIKI_V: return AK_V; + case DIKI_X: return AK_X; + + case DIKI_0: return AK_0; + case DIKI_1: return AK_1; + case DIKI_2: return AK_2; + case DIKI_3: return AK_3; + case DIKI_4: return AK_4; + case DIKI_5: return AK_5; + case DIKI_6: return AK_6; + case DIKI_7: return AK_7; + case DIKI_8: return AK_8; + case DIKI_9: return AK_9; + + case DIKI_KP_0: return AK_NP0; + case DIKI_KP_1: return AK_NP1; + case DIKI_KP_2: return AK_NP2; + case DIKI_KP_3: return AK_NP3; + case DIKI_KP_4: return AK_NP4; + case DIKI_KP_5: return AK_NP5; + case DIKI_KP_6: return AK_NP6; + case DIKI_KP_7: return AK_NP7; + case DIKI_KP_8: return AK_NP8; + case DIKI_KP_9: return AK_NP9; + case DIKI_KP_DIV: return AK_NPDIV; + case DIKI_KP_MULT: return AK_NPMUL; + case DIKI_KP_MINUS: return AK_NPSUB; + case DIKI_KP_PLUS: return AK_NPADD; + case DIKI_KP_DECIMAL: return AK_NPDEL; + case DIKI_KP_ENTER: return AK_ENT; + + case DIKI_F1: return AK_F1; + case DIKI_F2: return AK_F2; + case DIKI_F3: return AK_F3; + case DIKI_F4: return AK_F4; + case DIKI_F5: return AK_F5; + case DIKI_F6: return AK_F6; + case DIKI_F7: return AK_F7; + case DIKI_F8: return AK_F8; + case DIKI_F9: return AK_F9; + case DIKI_F10: return AK_F10; + + case DIKI_BACKSPACE: return AK_BS; + case DIKI_DELETE: return AK_DEL; + case DIKI_CONTROL_L: return AK_CTRL; + case DIKI_CONTROL_R: return AK_RCTRL; + case DIKI_TAB: return AK_TAB; + case DIKI_ALT_L: return AK_LALT; + case DIKI_ALT_R: case DIKI_ALTGR: return AK_RALT; + case DIKI_META_R: return AK_RAMI; + case DIKI_META_L: return AK_LAMI; + case DIKI_ENTER: return AK_RET; + case DIKI_SPACE: return AK_SPC; + case DIKI_SHIFT_L: return AK_LSH; + case DIKI_SHIFT_R: return AK_RSH; + case DIKI_ESCAPE: return AK_ESC; + + case DIKI_INSERT: return AK_HELP; + case DIKI_HOME: return AK_NPLPAREN; + case DIKI_END: return AK_NPRPAREN; + case DIKI_CAPS_LOCK: return AK_CAPSLOCK; + + case DIKI_UP: return AK_UP; + case DIKI_DOWN: return AK_DN; + case DIKI_LEFT: return AK_LF; + case DIKI_RIGHT: return AK_RT; + + case DIKI_PAGE_UP: return AK_RAMI; /* PgUp mapped to right amiga */ + case DIKI_PAGE_DOWN: return AK_LAMI; /* PgDn mapped to left amiga */ + + default: return -1; + } +} + +static int +decode_us( DFBInputDeviceKeyIdentifier id ) +{ + switch(id) { + /* US specific */ + case DIKI_A: return AK_A; + case DIKI_M: return AK_M; + case DIKI_Q: return AK_Q; + case DIKI_Y: return AK_Y; + case DIKI_W: return AK_W; + case DIKI_Z: return AK_Z; + case DIKI_BRACKET_LEFT: return AK_LBRACKET; + case DIKI_BRACKET_RIGHT: return AK_RBRACKET; + case DIKI_COMMA: return AK_COMMA; + case DIKI_PERIOD: return AK_PERIOD; + case DIKI_SLASH: return AK_SLASH; + case DIKI_SEMICOLON: return AK_SEMICOLON; + case DIKI_MINUS_SIGN: return AK_MINUS; + case DIKI_EQUALS_SIGN: return AK_EQUAL; + case DIKI_QUOTE_RIGHT: return AK_QUOTE; + case DIKI_QUOTE_LEFT: return AK_BACKQUOTE; + case DIKI_BACKSLASH: return AK_BACKSLASH; + default: return -1; + } +} + +static int +keyid2amiga( DFBInputDeviceKeyIdentifier id, int pressed ) +{ + int as, index = 0, hkreturn = -1, returnnow = 0; + + /* Handle hotkeys */ + if (pressed) { + int i, j; + for (i = 0; hotkeys[i].ids[0] != 0; i++) { + for (j = 0; hotkeys[i].ids[j] != 0; j++) { + if (id == hotkeys[i].ids[j]) { + hotkeys[i].mask &= ~(1 << j); + if (hotkeys[i].mask == 0) { + returnnow = 1; + hkreturn = hotkeys[i].retval; + } + } + } + } + } else { + int i, j; + for (i = 0; hotkeys[i].ids[0] != 0; i++) { + for (j = 0; hotkeys[i].ids[j] != 0; j++) { + if (id == hotkeys[i].ids[j]) { + hotkeys[i].mask |= (1 << j); + } + } + } + } + if (returnnow) + return -2; + + /* Handle normal keys */ + as = kc_decode( id ); + + /* Handle keyboard languages */ + if (as == -1) { + switch (currprefs.keyboard_lang) { + case KBD_LANG_US: + as = decode_us( id ); + break; + default: + as = -1; + break; + } + } + return as; +} + +void +handle_events( void ) +{ + DFBEvent e; + + gui_handle_events(); + + while (1) { + if (buffer->HasEvent( buffer ) != DFB_OK) + break; + + if (buffer->GetEvent( buffer, &e ) != DFB_OK) + break; + + if (e.clazz == DFEC_INPUT) { + /* Handle input events (fullscreen) */ + + DFBInputEvent event = e.input; + switch (event.type) { + case DIET_KEYPRESS: + { + int kc = keyid2amiga( event.key_id, 1 ); + + if (kc == -2) { + int i; + for (i = 0; hotkeys[i].ids[0] != 0; i++) + if (!hotkeys[i].mask && hotkeys[i].handler) + hotkeys[i].handler(); + break; + } + if (kc == -1) + break; + + if (!keystate[kc]) { + keystate[kc] = 1; + record_key( kc << 1 ); + } + } + break; + case DIET_KEYRELEASE: + { + int kc = keyid2amiga( event.key_id, 0 ); + + if (kc < 0) + break; + + keystate[kc] = 0; + record_key( (kc << 1) | 1 ); + + } + break; + case DIET_BUTTONPRESS: + switch (event.button) { + case DIBI_LEFT: + buttonstate[0] = 1; + break; + case DIBI_MIDDLE: + buttonstate[1] = 1; + break; + case DIBI_RIGHT: + buttonstate[2] = 1; + break; + } + break; + case DIET_BUTTONRELEASE: + switch (event.button) { + case DIBI_LEFT: + buttonstate[0] = 0; + break; + case DIBI_MIDDLE: + buttonstate[1] = 0; + break; + case DIBI_RIGHT: + buttonstate[2] = 0; + break; + } + break; + case DIET_AXISMOTION: + { + int x = lastmx, y = lastmy; + newmousecounters = 0; + + if (event.flags & DIEF_AXISABS) { + x = y = event.axisabs; + } else if (event.flags & DIEF_AXISREL) { + x = lastmx + event.axisrel; + y = lastmy + event.axisrel; + } + switch (event.axis) { + case DIAI_X: + lastmx = x; + break; + case DIAI_Y: + lastmy = y; + break; + } + } + break; + } + } else if (e.clazz == DFEC_WINDOW) { + /* Handle window events */ + + DFBWindowEvent event = e.window; + switch (event.type) { + case DWET_KEYDOWN: + { + int kc = keyid2amiga( event.key_id, 1 ); + + if (kc == -2) { + int i; + for (i = 0; hotkeys[i].ids[0] != 0; i++) + if (!hotkeys[i].mask && hotkeys[i].handler) + hotkeys[i].handler(); + break; + } + if (kc == -1) + break; + + if (!keystate[kc]) { + keystate[kc] = 1; + record_key( kc << 1 ); + } + } + break; + case DWET_KEYUP: + { + int kc = keyid2amiga( event.key_id, 0 ); + + if (kc < 0) + break; + + keystate[kc] = 0; + record_key( (kc << 1) | 1 ); + + } + break; + case DWET_BUTTONDOWN: + switch (event.button) { + case DIBI_LEFT: + buttonstate[0] = 1; + break; + case DIBI_MIDDLE: + buttonstate[1] = 1; + break; + case DIBI_RIGHT: + buttonstate[2] = 1; + break; + } + break; + case DWET_BUTTONUP: + switch (event.button) { + case DIBI_LEFT: + buttonstate[0] = 0; + break; + case DIBI_MIDDLE: + buttonstate[1] = 0; + break; + case DIBI_RIGHT: + buttonstate[2] = 0; + break; + } + break; + case DWET_MOTION: + newmousecounters = 0; + lastmx = event.x; + lastmy = event.y; + break; + } + } + } + + if ((keystate[AK_CTRL] || keystate[AK_RCTRL]) && keystate[AK_LAMI] && keystate[AK_RAMI]) + uae_reset(); +} + +void +target_save_options( FILE *f, struct uae_prefs *p ) +{ + fprintf( f, "directfb.layer_id=%d\n", p->directfb_layer_id ); + fprintf( f, "directfb.joy0_id=%d\n", p->directfb_joy0_id ); + fprintf( f, "directfb.joy1_id=%d\n", p->directfb_joy1_id ); +} + +int +target_parse_option( struct uae_prefs *p, char *option, char *value ) +{ + return cfgfile_intval( option, value, "layer_id", + &p->directfb_layer_id, 1 ) || + cfgfile_intval( option, value, "joy0_id", + &p->directfb_joy0_id, 1 ) || + cfgfile_intval( option, value, "joy1_id", + &p->directfb_joy0_id, 1 ); +} Index: uae/src/main.c diff -u uae/src/main.c:1.1.1.1 uae/src/main.c:1.2 --- uae/src/main.c:1.1.1.1 Mon Jan 6 15:37:07 2003 +++ uae/src/main.c Mon Jan 6 16:23:47 2003 @@ -43,6 +43,10 @@ #include "SDL.h" #endif +#ifdef USE_DIRECTFB +#include +#endif + long int version = 256*65536L*UAEMAJOR + 65536L*UAEMINOR + UAESUBREV; struct uae_prefs currprefs, changed_prefs; @@ -145,6 +149,10 @@ p->win32_iconified_nosound = 0; p->win32_no_overlay = 0; + p->directfb_layer_id = 0; + p->directfb_joy0_id = 0; + p->directfb_joy1_id = 0; + p->immediate_blits = 0; p->collision_level = 1; p->fast_copper = 1; @@ -458,6 +466,9 @@ #ifdef USE_SDL SDL_Init (SDL_INIT_EVERYTHING | SDL_INIT_NOPARACHUTE); +#endif +#ifdef USE_DIRECTFB + DirectFBInit( &argc, &argv ); #endif default_prefs (&currprefs); Index: uae/src/include/options.h diff -u uae/src/include/options.h:1.1.1.1 uae/src/include/options.h:1.2 --- uae/src/include/options.h:1.1.1.1 Mon Jan 6 15:37:07 2003 +++ uae/src/include/options.h Mon Jan 6 16:23:47 2003 @@ -118,6 +118,10 @@ int win32_no_overlay; /* If this is set, we won't try and use any RGB overlays */ int win32_automount_drives; + unsigned int directfb_layer_id; + unsigned int directfb_joy0_id; + unsigned int directfb_joy1_id; + int curses_reverse_video; }; Index: uae/src/targets/t-directfb.h diff -u /dev/null uae/src/targets/t-directfb.h:1.1 --- /dev/null Mon Jan 6 16:33:12 2003 +++ uae/src/targets/t-directfb.h Mon Jan 6 16:20:33 2003 @@ -0,0 +1,19 @@ + /* + * UAE - The Un*x Amiga Emulator + * + * Target specific stuff, DirectFB version + * + * Copyright (C) 2002 Ville Syrjala + */ + +#define TARGET_NAME "directfb" + +#define OPTIONSFILENAME ".uaerc" +#define OPTIONS_IN_HOME + +#define DEFPRTNAME "lpr" +#define DEFSERNAME "/dev/ttyS1" + +#define PICASSO96_SUPPORTED + +#define write_log write_log_standard